无法注入提供者
Cannot inject provider
Angular 1.6
我开发了一个dashboard application。已注册的仪表板组件有两个静态定义的 ui.router
状态:home-dashboard
和 other-dashboard
。
现在我想根据仪表板数据动态定义 ui.router
状态。为此,我在 app.config
内做了一个循环。但是为了获取仪表板数据,StorageService
provider 应该被注入到配置中。
收到的错误是:
Error: [$injector:unpr] Unknown provider: StorageService
如何注入提供者?有没有更好的方法来实现我的目标?
此外,我尝试将 $stateProvider
移动到父控制器 dashboardController
中。通过将它附加到 app.config
内的应用程序,如 app.stateProvider = $stateProvider;
并导出应用程序,将 return default app;
放在 app.js
文件的末尾。
我得到的错误是 'return' outside of function
。
Provider services/storage.service.js
(是一个模拟API的class,以后会从DB获取数据):
class Storage {
constructor () {
this.dashboards = {
'home': {
id: '1',
name: 'Home',
view: 'home',
url: '/home',
component: 'homeDashboard',
widgets: [{
col: 0,
row: 0,
sizeY: 1,
sizeX: 1,
name: "Widget 1"
}, {
col: 2,
row: 1,
sizeY: 1,
sizeX: 1,
name: "Widget 2"
}]
},
'other': {
id: '2',
name: 'Other',
view: 'other',
url: '/other',
component: 'otherDashboard',
widgets: [{
col: 1,
row: 1,
sizeY: 1,
sizeX: 2,
name: "Other Widget 1"
}, {
col: 1,
row: 3,
sizeY: 1,
sizeX: 1,
name: "Other Widget 2"
}]
}
};
}
saveDashboards(dashboards) {
this.dashboards = dashboards;
}
listDashboards() {
return this.dashboards;
}
$get() {
return this.dashboards;
}
}
export { Storage };
app.js
import { DashboardCtrl } from './controllers/dashboardController';
import { homeDashboard } from './dashboards/home/homeDashboard.component';
import { otherDashboard } from './dashboards/other/otherDashboard.component';
import { aWidget } from './widgets/a_widget/aWidget.component';
import { Storage } from './services/storage.service.js';
import { Object2Array } from './filters/object2Array.js';
const app = angular.module('dashboardApp', [
'ui.router',
'ui.bootstrap',
'gridster'
])
.controller('DashboardCtrl', DashboardCtrl)
.component('aWidget', aWidget)
.component('homeDashboard', homeDashboard)
.component('otherDashboard', otherDashboard)
//.factory('StorageService', () => new Storage())
.provider('StorageService', Storage)
.filter('object2Array', Object2Array);
app.config(function ($urlRouterProvider, $stateProvider, StorageService) {
const dashboards = StorageService.listDashboards();
_.forEach(dashboards, function (d) {
$stateProvider.state({
name: d.view,
url: d.url,
component: d.component
});
});
/*
const homeState = {
name: 'home',
url: '/home',
component: 'homeDashboard'
};
const otherState = {
name: 'other',
url: '/other',
component: 'otherDashboard'
};
$stateProvider.state(homeState);
$stateProvider.state(otherState);
*/
$urlRouterProvider.otherwise('/home');
});
应用树:
../angular-dashboard/
├── LICENSE
├── README.md
├── dist
├── package.json
├── src
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ └── dashboardController.js
│ │ ├── dashboards
│ │ │ ├── home
│ │ │ │ ├── homeDashboard.component.js
│ │ │ │ ├── homeDashboard.controller.js
│ │ │ │ └── templates
│ │ │ │ └── homeDashboard.template.html
│ │ │ └── other
│ │ │ ├── otherDashboard.component.js
│ │ │ ├── otherDashboard.controller.js
│ │ │ └── templates
│ │ │ └── otherDashboard.template.html
│ │ ├── filters
│ │ │ └── object2Array.js
│ │ ├── services
│ │ │ └── storage.service.js
│ │ └── widgets
│ │ └── a_widget
│ │ ├── aWidget.component.js
│ │ ├── aWidget.controller.js
│ │ ├── aWidget.settings.controller.js
│ │ └── templates
│ │ ├── aWidget.settings.template.html
│ │ └── aWidget.template.html
│ ├── index.html
│ └── style
│ ├── style-common.css
│ └── style.css
└── webpack.config.js
15 directories, 22 files
UI 看:
StorageService
是 provider
服务,它在配置阶段作为 StorageServiceProvider
服务提供者可用,在 运行 阶段作为 StorageService
服务实例可用。
当作为 StorageServiceProvider
注入时,它将是 Storage
class 的实例,当作为 StorageService
注入时,它将是 return $get
方法(dashboards
对象)的值。
当服务实例依赖于其他服务时,需要provider
、factory
和service
服务。否则可以使用 constant
或 value
服务。
Storage
class 太过分了,因为它所做的只是为普通对象提供访问器方法。它可以是 constant
服务,它将在配置和 运行 阶段以相同的名称提供:
app.constant('StorageService', {
home: { ... },
...
});
可以直接在控制器中定义路由。
首先,我们需要为控制器提供$stateProvider
。
...
app.config(function ($urlRouterProvider, $stateProvider) {
app.stateProvider = $stateProvider;
$urlRouterProvider.otherwise('/home');
});
export default app;
其次,我们在控制器内部定义状态。
import app from '../app';
...
const DashboardCtrl = function ($scope, $timeout, StorageService) {
...
forEach($scope.dashboards, function (dashboard) {
app.stateProvider.state({
name: dashboard.name,
url: dashboard.url,
component: dashboard.component
});
});
});
Angular 1.6
我开发了一个dashboard application。已注册的仪表板组件有两个静态定义的 ui.router
状态:home-dashboard
和 other-dashboard
。
现在我想根据仪表板数据动态定义 ui.router
状态。为此,我在 app.config
内做了一个循环。但是为了获取仪表板数据,StorageService
provider 应该被注入到配置中。
收到的错误是:
Error: [$injector:unpr] Unknown provider: StorageService
如何注入提供者?有没有更好的方法来实现我的目标?
此外,我尝试将 $stateProvider
移动到父控制器 dashboardController
中。通过将它附加到 app.config
内的应用程序,如 app.stateProvider = $stateProvider;
并导出应用程序,将 return default app;
放在 app.js
文件的末尾。
我得到的错误是 'return' outside of function
。
Provider services/storage.service.js
(是一个模拟API的class,以后会从DB获取数据):
class Storage {
constructor () {
this.dashboards = {
'home': {
id: '1',
name: 'Home',
view: 'home',
url: '/home',
component: 'homeDashboard',
widgets: [{
col: 0,
row: 0,
sizeY: 1,
sizeX: 1,
name: "Widget 1"
}, {
col: 2,
row: 1,
sizeY: 1,
sizeX: 1,
name: "Widget 2"
}]
},
'other': {
id: '2',
name: 'Other',
view: 'other',
url: '/other',
component: 'otherDashboard',
widgets: [{
col: 1,
row: 1,
sizeY: 1,
sizeX: 2,
name: "Other Widget 1"
}, {
col: 1,
row: 3,
sizeY: 1,
sizeX: 1,
name: "Other Widget 2"
}]
}
};
}
saveDashboards(dashboards) {
this.dashboards = dashboards;
}
listDashboards() {
return this.dashboards;
}
$get() {
return this.dashboards;
}
}
export { Storage };
app.js
import { DashboardCtrl } from './controllers/dashboardController';
import { homeDashboard } from './dashboards/home/homeDashboard.component';
import { otherDashboard } from './dashboards/other/otherDashboard.component';
import { aWidget } from './widgets/a_widget/aWidget.component';
import { Storage } from './services/storage.service.js';
import { Object2Array } from './filters/object2Array.js';
const app = angular.module('dashboardApp', [
'ui.router',
'ui.bootstrap',
'gridster'
])
.controller('DashboardCtrl', DashboardCtrl)
.component('aWidget', aWidget)
.component('homeDashboard', homeDashboard)
.component('otherDashboard', otherDashboard)
//.factory('StorageService', () => new Storage())
.provider('StorageService', Storage)
.filter('object2Array', Object2Array);
app.config(function ($urlRouterProvider, $stateProvider, StorageService) {
const dashboards = StorageService.listDashboards();
_.forEach(dashboards, function (d) {
$stateProvider.state({
name: d.view,
url: d.url,
component: d.component
});
});
/*
const homeState = {
name: 'home',
url: '/home',
component: 'homeDashboard'
};
const otherState = {
name: 'other',
url: '/other',
component: 'otherDashboard'
};
$stateProvider.state(homeState);
$stateProvider.state(otherState);
*/
$urlRouterProvider.otherwise('/home');
});
应用树:
../angular-dashboard/
├── LICENSE
├── README.md
├── dist
├── package.json
├── src
│ ├── app
│ │ ├── app.js
│ │ ├── controllers
│ │ │ └── dashboardController.js
│ │ ├── dashboards
│ │ │ ├── home
│ │ │ │ ├── homeDashboard.component.js
│ │ │ │ ├── homeDashboard.controller.js
│ │ │ │ └── templates
│ │ │ │ └── homeDashboard.template.html
│ │ │ └── other
│ │ │ ├── otherDashboard.component.js
│ │ │ ├── otherDashboard.controller.js
│ │ │ └── templates
│ │ │ └── otherDashboard.template.html
│ │ ├── filters
│ │ │ └── object2Array.js
│ │ ├── services
│ │ │ └── storage.service.js
│ │ └── widgets
│ │ └── a_widget
│ │ ├── aWidget.component.js
│ │ ├── aWidget.controller.js
│ │ ├── aWidget.settings.controller.js
│ │ └── templates
│ │ ├── aWidget.settings.template.html
│ │ └── aWidget.template.html
│ ├── index.html
│ └── style
│ ├── style-common.css
│ └── style.css
└── webpack.config.js
15 directories, 22 files
UI 看:
StorageService
是 provider
服务,它在配置阶段作为 StorageServiceProvider
服务提供者可用,在 运行 阶段作为 StorageService
服务实例可用。
当作为 StorageServiceProvider
注入时,它将是 Storage
class 的实例,当作为 StorageService
注入时,它将是 return $get
方法(dashboards
对象)的值。
provider
、factory
和service
服务。否则可以使用 constant
或 value
服务。
Storage
class 太过分了,因为它所做的只是为普通对象提供访问器方法。它可以是 constant
服务,它将在配置和 运行 阶段以相同的名称提供:
app.constant('StorageService', {
home: { ... },
...
});
可以直接在控制器中定义路由。
首先,我们需要为控制器提供$stateProvider
。
...
app.config(function ($urlRouterProvider, $stateProvider) {
app.stateProvider = $stateProvider;
$urlRouterProvider.otherwise('/home');
});
export default app;
其次,我们在控制器内部定义状态。
import app from '../app';
...
const DashboardCtrl = function ($scope, $timeout, StorageService) {
...
forEach($scope.dashboards, function (dashboard) {
app.stateProvider.state({
name: dashboard.name,
url: dashboard.url,
component: dashboard.component
});
});
});