Angular brak dostawcy usługi NameService


326

Mam problem z ładowaniem klasy do komponentu Angular. Od dłuższego czasu próbuję go rozwiązać; Próbowałem nawet połączyć to wszystko w jednym pliku. Mam:

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

services / NameService.ts

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

Wciąż pojawia się komunikat o błędzie No provider for NameService.

Czy ktoś może mi pomóc w wykryciu problemu z moim kodem?


6
od Alpha 42: @Component ({dostawcy: [NameService]})
timmz 16.10.15

Odpowiedzi:


470

Musisz użyć providerszamiastinjectables

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

Wypełnij przykładowy kod tutaj .


7
@unobf instrukcje importu nie wyglądają na zepsute. Poprzednia odpowiedź może być poprawna dla starszych alf bibliotek angular2. Oryginalny przewodnik odnosi się do alpha-28, używam alpha 35. Podaję też link do pełnej próbki kodu, więc myślę, że dostarczyłem sporo informacji.
Klas Mellbourn

4
Aktualizacja dla przyszłych pracowników Google: korzystanie providersz najnowszej wersji beta (beta 0).
nathanhleung

@nathanhleung zarówno wiązania i dostawców pracy - jest to tymczasowe lub są po prostu robi to samo wewnętrznie
Simon_Weaver

@Simon_Weaver hmm mogły się zmienić go w najnowszej wersji beta - w beta.0 nie mogę zmusić go do pracy zbindings
nathanhleung

1
co jeśli usługa jest używana z innej usługi? dodałem go do dostawców modułów, które - jak sądziłem - udostępnią go na całym świecie, ale nadal pojawia się ten błąd
Sonic Soul,

79

W Angular 2 są trzy miejsca, w których możesz „świadczyć” usługi:

  1. bootstrap
  2. składnik główny
  3. inne elementy lub dyrektywy

„Opcja dostawcy ładowania początkowego służy do konfigurowania i zastępowania własnych wstępnie zarejestrowanych usług Angular, takich jak obsługa routingu”. - odniesienie

Jeśli chcesz mieć tylko jedno wystąpienie usługi NameService w całej aplikacji (tj. Singleton), dołącz ją do providerstablicy głównego komponentu:

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

Plunker

Jeśli wolisz mieć jedną instancję na komponent, zamiast tego użyj providerstablicy w obiekcie konfiguracyjnym komponentu:

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

Więcej informacji można znaleźć w dokumencie Hierarchical Injectors .


4
To jest naprawdę dobra odpowiedź. Wyjaśnia ponadto różnice między deklarowaniem usługi w komponencie głównym a deklarowaniem w innych komponentach potomnych.
Taf

34

Od Angular 2 Beta:

Dodaj @Injectabledo swojej usługi jako:

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

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

    getNames() {
        return this.names;
    }
}

i do konfiguracji swojego komponentu dodaj providers:

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

22

Powinieneś być wstrzykiwanie NameServicewewnątrz providerstablicę swoją AppModule„s NgModulemetadanych.

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

}

Jeśli chcesz utworzyć zależność dla określonego poziomu komponentu bez zawracania sobie głowy stanem aplikacji, możesz wstrzyknąć tę zależność do providersopcji metadanych komponentów , takich jak wyświetlana zaakceptowana odpowiedź @Klass .


Próbowałem dodać usługę w app.module.shared.ts w sekcji @NgModule: dostawcy: [DataManagerService], ale nadal pojawia się błąd: Błąd: Brak dostawcy usługi DataManagerService!
Paul

1
@Paul, czy wstrzykujesz swoje usługi do odpowiedniego modułu? i czy DataManagerServicema @Injectablenad tym dekoratora?
Pankaj Parkar

15

Szokująco, składnia zmieniła się ponownie w najnowszej wersji Angulara :-) Z dokumentacji Angulara 6 :

Począwszy od Angular 6.0, preferowanym sposobem tworzenia usług singletonowych jest określenie w usłudze, że powinna być udostępniana w katalogu głównym aplikacji. Odbywa się to poprzez ustawienie pod warunkiem, że root zostanie umieszczony na dekoratorze @Injectable usługi:

src / app / user.service.0.ts

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

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

14

Powinieneś wstrzykiwać NameService do tablicy dostawców metadanych NgModule swojego AppModule.

@NgModule({
   providers: [MyService]
})

i pamiętaj, aby zaimportować do komponentu tę samą nazwę (rozróżnia duże i małe litery), ponieważ SystemJs rozróżnia małe i wielkie litery (zgodnie z projektem). Jeśli użyjesz innej nazwy ścieżki w plikach projektu, takich jak to:

main.module.ts

import { MyService } from './MyService';

twój-komponent.ts

import { MyService } from './Myservice';

wtedy System js wykona podwójny import


1
Świetny! Podczas używania beczek do grupowania importów napotkałem ten błąd. Twoja wskazówka SystemJS pomogła mi :)
Jony Adamit

12

W Angular v2 i nowszych jest teraz:

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


7

Angular 2 zmienił się, oto jak powinna wyglądać góra twojego kodu:

import {
  ComponentAnnotation as Component,
  ViewAnnotation as View, bootstrap
} from 'angular2/angular2';
import {NameService} from "./services/NameService";

@Component({
  selector: 'app',
  appInjector: [NameService]
})

Możesz także skorzystać z funkcji pobierających i ustawiających w swojej usłudze:

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

Następnie w swojej aplikacji możesz po prostu zrobić:

this.names = nameService.names;

Sugeruję, aby przejść do strony plnkr.co i utworzyć nową wersję Angular 2 (ES6) i sprawić, by najpierw tam działała. Wszystko skonfiguruje dla Ciebie. Gdy już tam zacznie działać, skopiuj go do innego środowiska i sprawdź wszystkie problemy z tym środowiskiem.


6

Błąd No provider for NameServicejest częstym problemem, z którym boryka się wielu początkujących Angular2.

Powód : Przed użyciem dowolnej usługi niestandardowej musisz najpierw zarejestrować ją w NgModule, dodając ją do listy dostawców:

Rozwiązanie:

@NgModule({
    imports: [...],
    providers: [CustomServiceName]
})


4

Cześć. Możesz użyć tego w swoim pliku .ts:

najpierw zaimportuj usługę do tego pliku .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Następnie w tym samym pliku możesz dodać providers: [Your_Service_Name]:

 @Component({
      selector: 'my-app',
      providers: [Your_Service_Name],
      template: `
        <h1>Hello World</h1> `   
    })

4

Dodaj go do dostawców, których nie można wstrzykiwać

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

3

W Angular możesz zarejestrować usługę na dwa sposoby:

1. Zarejestruj usługę w module lub komponencie głównym

Efekty:

  • Dostępne we wszystkich komponentach
  • Dostępne dożywotniej aplikacji

Zachowaj ostrożność, jeśli zarejestrujesz usługę w leniwie załadowanym module:

  • Usługa jest dostępna tylko dla komponentów zadeklarowanych w tym module

  • Usługa będzie dostępna dożywotniej aplikacji tylko po załadowaniu modułu

2. Zarejestruj usługę w dowolnym innym komponencie aplikacji

Efekty:

  • Zostanie wstrzyknięta osobna instancja Usługi do komponentu

Należy zachować ostrożność, jeśli zarejestrujesz usługę w jakimkolwiek innym komponencie aplikacji

  • Instancja wstrzykniętej usługi będzie dostępna tylko dla komponentu i wszystkich jego elementów podrzędnych.

  • Instancja będzie dostępna przez cały okres istnienia komponentu.


2

Musisz dodać go do tablicy dostawców, która obejmuje wszystkie zależności od twojego komponentu.

Spójrz na ten rozdział w dokumentacji kątowej:

Rejestrowanie dostawców w komponencie

Oto zmieniony HeroesComponent, który rejestruje usługę HeroService w tablicy dostawców.

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

import { HeroService } from './hero.service';

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  <h2>Heroes</h2>
  <hero-list></hero-list>
  `
})
export class HeroesComponent { }

Kiedy używać NgModule w porównaniu ze składnikiem aplikacji

Z jednej strony dostawca w module NgModule jest zarejestrowany we wtryskiwaczu root. Oznacza to, że każdy dostawca zarejestrowany w NgModule będzie dostępny w całej aplikacji.

Z drugiej strony dostawca zarejestrowany w komponencie aplikacji jest dostępny tylko dla tego komponentu i wszystkich jego elementów potomnych.

Tutaj usługa APP_CONFIG musi być dostępna w całej aplikacji, więc jest zarejestrowana w tablicy dostawców AppModule @NgModule. Ponieważ jednak usługa HeroService jest używana tylko w obszarze funkcji Heroes i nigdzie indziej, warto zarejestrować ją w HeroesComponent.

Zobacz także „Czy powinienem dodawać dostawców aplikacji do głównego modułu AppModule lub głównego elementu AppComponent?” w FAQ NgModule.

Więc w twoim przypadku, po prostu zmień zastrzyki na dostawców takich jak poniżej:

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

Również w nowych wersjach Angular, @View i niektórych innych rzeczach już nie ma.

Aby uzyskać więcej informacji, odwiedź tutaj .


2

dodaj swoją usługę do tablicy dostawców [] w pliku app.module.ts. Jak poniżej

// tutaj moja usługa to CarService

app.module.ts

import {CarsService} from './cars.service';

providers: [CarsService] // you can include as many services you have 

1

Angular2 wymaga zadeklarowania wszystkich elementów do wstrzykiwania w wywołaniu funkcji bootstrap. Bez tego twoja usługa nie jest przedmiotem do wstrzyknięcia.

bootstrap(MyAppComponent,[NameService]);

1
To nie jest całkiem poprawne. Możemy zawrzeć usługę w bootstrap () lub w providerstablicy w obiekcie konfiguracyjnym komponentu. Jeśli jest uwzględniony w providerstablicy, otrzymujemy jedną instancję na związany komponent. Więcej informacji można znaleźć w dokumencie Hierarchical Injectors .
Mark Rajcok

tak, jak powiedział @MarkRajcok, zapewniamy również tylko te usługi w czasie bootstrapu, z których musimy korzystać w całej aplikacji. dzięki temu nie musieliśmy za każdym razem wstrzykiwać dostawcy, ponieważ utworzy on instancję dla każdego komponentu.
Pardeep Jain

1

Dodaj @Injectable do swojej usługi jako:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

i w swoim komponencie dodaj dostawców jako:

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

lub jeśli chcesz uzyskać dostęp do swojej usługi w całej aplikacji, możesz przekazać dostawcę aplikacji


1

Zablokować cytat

Rejestrowanie dostawców w komponencie

Oto zmieniony HeroesComponent, który rejestruje usługę HeroService w tablicy dostawców.

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

import { HeroService } from './hero.service';

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.