没有服务提供商

时间:2016-06-19 18:41:16

标签: angular angular2-services angular2-providers

我正在尝试使用2.0.0-beta.17进入angular2。我想从服务中读取数据,但无论我做什么,我都会得到例外:

No provider for LanguageBrowser!

我在这里经历了几十个相同的问题,但没有一个有效。

这是我的服务类:

import {Injectable} from "angular2/core";
import {Language} from "../models/language.model";

@Injectable()
export class LanguageService {
    ReadAll(onNext: (json: any) => void) {
        return [
            new Language({ Id: 1, Name: "German" }),
            new Language({ Id: 2, Name: "English" }),
            new Language({ Id: 3, Name: "Dutch" })
        ];
    }
}

语言是一个简单的打字稿类,应该最终从webservice调用中检索出来,但我不是那么远。

export class Language {
    public Id: number;
    public Name: string;

    constructor(json: any) {
        if (json) {
            this.Id = json.Id || 0;
            this.Name = json.Name || "";
        }
    }
}

LanguageService由LanguageBrowser组件

使用
import {Component} from "angular2/core"
import {Language} from "../models/language.model"
import {LanguageDetail} from "./language-detail.component"
import {LanguageCollection} from "./language-collection.component"
import {LanguageService} from "../services/language.service"

@Component({
    selector: "language-browser",
    template: `
        <language-collection [languages]="availableLanguages" (selectionChanged)="onSelectionChanged($event)"></language-collection>
        <language-detail [language]="selectedLanguage"></language-detail>
    `
    providers: [LanguageService],
    directives: [LanguageCollection, LanguageDetail]
})
export class LanguageBrowser {
    private selectedLanguage: Language;
    private availableLanguages: Language[];

    constructor(languageService: LanguageService) {
        languageService.ReadAll(json => this.availableLanguages = json);
    }

    onSelectionChanged(language) {
        this.selectedLanguage = language;
    }
}

LanguageCollection是另一个获取语言列表并在选择列表中的一种语言时发出事件的组件。 LanguageDetail只显示所选语言。它们都是不相关的(我猜),所以我会在这里排除它们。

另一个答案显示我添加了system-polyfills.js和es6-shim.js作为脚本包含但无济于事。这是我布局的相关部分:

<script src="~/js/jquery.js"></script>
<script src="~/js/bootstrap.js"></script>
<script src="~/js/system.js"></script>
<script src="~/js/system-polyfills.js"></script>
<script src="~/js/rx.js"></script>
<script src="~/js/typescript.js"></script>
<script src="~/js/es6-shim.js"></script>
<script src="~/js/angular2/angular2-polyfills.js"></script>
<script src="~/js/angular2/angular2.dev.js"></script>
<script src="~/js/angular2/http.dev.js"></script>
<script src="~/js/angular2/router.dev.js"></script>

<script>
        System.config({
            packages: {
                app: {
                    format: 'register',
                    defaultExtension: 'js'
                }
            }
        });
        System.import('app/boot');
</script>

启动只是看起来像这样:

import {bootstrap}    from "angular2/platform/browser"
import {AppComponent} from "./app.component"
import "rxjs/add/operator/map";

bootstrap(AppComponent);

和AppComponent一样:

import {Component} from "angular2/core";
import {LanguageBrowser} from "./components/language-browser.component";

@Component({
    selector: "app",
    template: `
        <language-browser></language-browser>
    `,
    directives: [LanguageBrowser]
})

export class AppComponent {
    public LanguageBrowser: LanguageBrowser;

    constructor(languageBrowser: LanguageBrowser) {
        this.LanguageBrowser = languageBrowser;
    }
}

package.json中的依赖项:

"dependencies": {
    "angular2": "2.0.0-beta.17",
    "bootstrap": "3.3.6",
    "es6-promise": "3.2.1",
    "es6-shim": "0.35.1",
    "jquery": "2.2.4",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.6",
    "systemjs": "0.19.30",
    "typescript": "1.8.10",
    "zone.js": "0.6.12"
  },
  "devDependencies": {
    "gulp": "3.9.1",
    "del": "2.2.0"
  },
  "peerDependencies": {
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.6"
  }

由于npm安装告诉我angular2想要reflect-metadata和rxjs的peerDependencies,我只是将它们包含在peerDependencies中。我也将它们作为常规依赖项而没有任何变化。

显然我错过了一些东西,但我无法找出它可能是什么。经历了几个关于angular2的教程,但没有一个能做到这一点。

2 个答案:

答案 0 :(得分:3)

使用ViewChild

@Component({
    selector: "app",
    template: `
        <language-browser></language-browser>
    `,
    directives: [LanguageBrowser]
})

export class AppComponent {
    @ViewChild(LanguageBrowser) lb:LanguageBrowser;

    constructor() {}
    ngAfterViewInit() {
        let yey = this.lb.availableLanguages;
    }
}

另外,尽量避免在构造函数中执行任何操作,学习lifecycle hooks并使用它们。

答案 1 :(得分:1)

在Sasxa建议学习生命周期钩子和他提供的链接后,我实际上能够提出一个解决方案。我很确定有六种更简单的方法可以做到这一点,但除了在构造函数中注入LanguageService之外,我无法找到如何获取服务对象。

无论如何,这就是我现在正在做的事情:

import {Component, OnInit, ReflectiveInjector} from "angular2/core"
import {Language} from "../models/language.model"
import {LanguageDetail} from "./language-detail.component"
import {LanguageCollection} from "./language-collection.component"
import {LanguageService} from "../services/language.service"

@Component({
    selector: "language-browser",
    templateUrl: "./app/views/language-browser.html",
    providers: [LanguageService],
    directives: [LanguageCollection, LanguageDetail]
})
export class LanguageBrowser implements OnInit {
    private selectedLanguage: Language;
    private availableLanguages: Language[];

    ngOnInit() {
        var injector: ReflectiveInjector = ReflectiveInjector.resolveAndCreate([LanguageService]);
        var languageService: LanguageService = injector.get(LanguageService);

        this.availableLanguages = languageService.ReadAll();
    }

    onSelectionChanged(language) {
        this.selectedLanguage = language;
    }
}

如果有人解释为什么错误最初发生,我会很高兴听到它。