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:
- bootstrap
- rotkomponent
- 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: ... })
