typescript - Angular ingen leverandør for NameService


Jeg har et problem med å laste en klasse inn i en Angular-komponent. Jeg har prøvd å løse det lenge; jeg har til og med prøvd å samle alt i én fil. Det jeg har er:

Application.ts

/// <reference path="../typings/angular2/angular2.d.ts" />

import {Component,View,bootstrap,NgFor} from "angular2/angular2";
import {NameService} from "./services/NameService";

@Component({
    selector:'my-app',
    injectables: [NameService]
})
@View({
    template:'<h1>Hi {{name}}</h1>' +
    '<p>Friends</p>' +
    '<ul>' +
    '   <li *ng-for="#name of names">{{name}}</li>' +
    '</ul>',
    directives:[NgFor]
})

class MyAppComponent
{
    name:string;
    names:Array<string>;

    constructor(nameService:NameService)
    {
        this.name = 'Michal';
        this.names = nameService.getNames();
    }
}
bootstrap(MyAppComponent);

tjenester/NameService.ts

export class NameService {
    names: Array<string>;
    constructor() {
        this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }
    getNames()
    {
        return this.names;
    }
}

Jeg får stadig en feilmelding som sier Ingen leverandør for NameService.

Kan noen hjelpe meg med å finne problemet med koden min?

Svar #1

Du må bruke providers i stedet for injectables

@Component({
    selector: 'my-app',
    providers: [NameService]
})

Fullstendig kodesample her.

Svar #2

I Angular 2 finnes det tre steder du kan «tilby» tjenester:

  1. bootstrap
  2. rotkomponent
  3. andre komponenter eller direktiver

"Bootstrap-leverandøroppgaven er ment for å konfigurere og overstyre Angulars egne forhåndsregistrerte tjenester, slik som støtte for ruting." -- referanse

Hvis du bare vil ha én instans av NameService i hele appen din (dvs. Singleton), inkluder den da i providers-arrayet til rotkomponenten din:

@Component({
   providers: [NameService],
   ...
)}
export class AppComponent { ... }

Plunker

Hvis du heller vil ha en instans per komponent, bruk providers-arrayen i komponentens konfigurasjonsobjekt i stedet:

@Component({
   providers: [NameService],
   ...
)}
export class SomeOtherComponentOrDirective { ... }

Se dokumentasjonen om hierarkiske injektorer for mer informasjon.

Svar #3

Fra og med Angular 2 Beta:

Legg til @Injectable i tjenesten din som:

@Injectable()
export class NameService {
    names: Array<string>;

    constructor() {
        this.names = ["Alice", "Aarav", "Martín", "Shannon", "Ariana", "Kai"];
    }

    getNames() {
        return this.names;
    }
}

og i komponentkonfigurasjonen din legg til providers som:

@Component({
    selector: 'my-app',
    providers: [NameService]
})

Svar #4

Du bør injisere NameService inne i providers-arrayen i AppModules NgModule-metadata.

@NgModule({
   imports: [BrowserModule, ...],
   declarations: [...],
   bootstrap: [AppComponent],
   //inject providers below if you want single instance to be share amongst app
   providers: [MyService]
})
export class AppModule {

}

Hvis du ønsker å opprette en avhengighet for et bestemt komponentnivå uten å bekymre deg for tilstanden til applikasjonen din, kan du injisere den avhengigheten i komponentens providers-metadataalternativ som vist i det aksepterte @Klass-svaret.

Svar #5

Sjokkerende nok har syntaksen endret seg igjen i den nyeste versjonen av Angular :-) Fra Angular 6-dokumentasjonen:

Fra og med Angular 6.0 er den foretrukne måten å lage singleton-tjenester på å spesifisere i tjenesten at den skal leveres i applikasjonens rot. Dette gjøres ved å sette providedIn til root på tjenestens @Injectable-dekoratør:

src/app/user.service.0.ts

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class UserService {
}

Svar #6

Du bør injisere NameService inne i providers-arrayet til NgModule-metadataen til AppModule.

@NgModule({
   providers: [MyService]
})

og sørg for å importere i komponenten din med samme navn (store og små bokstaver må stemme), fordi SystemJs er store-/småbokstavfølsom (etter design). Hvis du bruker et annet banenavn i prosjektfilene dine som dette:

main.module.ts

import { MyService } from './MyService';

din-komponent.ts

import { MyService } from './Myservice';

da vil System js gjøre doble importer

Svar #7

I Angular v2 og nyere er det nå:

@Component({ selector: 'my-app', providers: [NameService], template: ... })

Relaterte artikler