无法注入提供者

Cannot inject provider

Angular 1.6

我开发了一个dashboard application。已注册的仪表板组件有两个静态定义的 ui.router 状态:home-dashboardother-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 看:

StorageServiceprovider 服务,它在配置阶段作为 StorageServiceProvider 服务提供者可用,在 运行 阶段作为 StorageService 服务实例可用。

当作为 StorageServiceProvider 注入时,它将是 Storage class 的实例,当作为 StorageService 注入时,它将是 return $get 方法(dashboards 对象)的值。

当服务实例依赖于其他服务时,需要

providerfactoryservice服务。否则可以使用 constantvalue 服务。

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
    });
  });
});