Angular kein Anbieter für NameService


325

Ich habe ein Problem beim Laden einer Klasse in eine Angular-Komponente. Ich habe lange versucht, es zu lösen; Ich habe sogar versucht, alles in einer einzigen Datei zusammenzufügen. Was ich habe ist:

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

Ich erhalte immer wieder eine Fehlermeldung No provider for NameService.

Kann mir jemand helfen, das Problem mit meinem Code zu erkennen?


6
ab Alpha 42: @Component ({provider: [NameService]})
timmz

Antworten:


470

Sie müssen providersanstelle von verwendeninjectables

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

Vollständiges Codebeispiel hier .


7
@unobf die import Anweisungen sehen für mich nicht kaputt aus. Die vorherige Antwort ist möglicherweise für ältere Alphas der Angular2-Bibliothek richtig. Die ursprüngliche Anleitung bezieht sich auf Alpha-28, ich verwende Alpha 35. Außerdem biete ich einen Link zu einem vollständigen Codebeispiel, sodass ich glaube, dass ich ziemlich viele Informationen bereitgestellt habe.
Klas Mellbourn

4
Ein Update für zukünftige Googler: providersArbeiten mit der neuesten Beta (Beta 0).
Nathanhleung

@ Nathanhleung beide Bindungen und Anbieter arbeiten - ist dies vorübergehend oder tun sie nur das gleiche intern
Simon_Weaver

@ Simon_Weaver hmm sie haben es vielleicht in der letzten Beta geändert - in Beta.0 Ich konnte es nicht zum bindings
Laufen bringen

1
Was ist, wenn der Dienst von einem anderen Dienst verwendet wird? Ich habe es
Sonic Soul

79

In Angular 2 gibt es drei Orte, an denen Sie Dienste "bereitstellen" können:

  1. Bootstrap
  2. Wurzelkomponente
  3. andere Komponenten oder Richtlinien

"Die Bootstrap-Provider-Option dient zum Konfigurieren und Überschreiben von Angulars eigenen vorregistrierten Diensten, z. B. der Routing-Unterstützung." - Referenz

Wenn Sie nur eine Instanz von NameService für Ihre gesamte App (z. B. Singleton) möchten, fügen Sie diese in das providersArray Ihrer Stammkomponente ein :

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

Plunker

Wenn Sie lieber eine Instanz pro Komponente haben möchten, verwenden Sie providersstattdessen das Array im Konfigurationsobjekt der Komponente:

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

Siehe die Hierarchical Injectors doc für weitere Informationen.


4
Das ist eine wirklich gute Antwort. Außerdem werden die Unterschiede zwischen der Deklaration des Dienstes in der Stammkomponente und der Deklaration in anderen untergeordneten Komponenten erläutert.
Taf

33

Ab Angular 2 Beta:

Fügen Sie @InjectableIhrem Service Folgendes hinzu:

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

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

    getNames() {
        return this.names;
    }
}

und fügen Sie Ihrer Komponentenkonfiguration Folgendes hinzu providers:

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

22

Sie sollten durch Einspritzen NameServiceinnerhalb providersArray Ihrer AppModule‚s NgModuleMetadaten.

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

}

Wenn Sie eine Abhängigkeit für eine bestimmte Komponentenebene erstellen möchten, ohne sich um den Status Ihrer Anwendung zu kümmern, können Sie diese Abhängigkeit von der providersOption für Komponentenmetadaten wie die angezeigte akzeptierte @ Klassen- Antwort einfügen .


Ich habe versucht, einen Dienst in app.module.shared.ts im Abschnitt @NgModule hinzuzufügen: Anbieter: [DataManagerService], erhalte aber immer noch den Fehler: Fehler: Kein Anbieter für DataManagerService!
Paul

1
@Paul injizieren Sie Ihren Service in das richtige Modul? und DataManagerServicehat @InjectableDekorateur darüber?
Pankaj Parkar

15

Erstaunlicherweise hat sich die Syntax in der neuesten Version von Angular erneut geändert :-) Aus den Angular 6-Dokumenten :

Ab Angular 6.0 besteht die bevorzugte Methode zum Erstellen von Singleton-Diensten darin, auf dem Dienst anzugeben, dass er im Anwendungsstamm bereitgestellt werden soll. Dies erfolgt durch Setzen von Bereitgestellt auf root im @ Injectable-Dekorator des Dienstes:

src / app / user.service.0.ts

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

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

14

Sie sollten NameService in das Provider-Array der NgModule-Metadaten Ihres AppModule einfügen.

@NgModule({
   providers: [MyService]
})

und stellen Sie sicher, dass Sie in Ihre Komponente denselben Namen importieren (Groß- und Kleinschreibung beachten), da bei SystemJs die Groß- und Kleinschreibung beachtet wird (beabsichtigt). Wenn Sie in Ihren Projektdateien einen anderen Pfadnamen wie folgt verwenden:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

dann führt System js doppelte Importe durch


1
Ausgezeichnet! Bei der Verwendung von Fässern zum Gruppieren von Importen ist dieser Fehler aufgetreten. Ihr SystemJS-Tipp hat mir geholfen :)
Jony Adamit

12

In Angular v2 und höher ist es jetzt:

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


7

Winkel 2 hat sich geändert. So sollte der obere Teil Ihres Codes aussehen:

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

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

Möglicherweise möchten Sie auch Getter und Setter in Ihrem Dienst verwenden:

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

Dann können Sie in Ihrer App einfach Folgendes tun:

this.names = nameService.names;

Ich schlage vor, Sie gehen zu plnkr.co und erstellen einen neuen Angular 2 (ES6) -Plunk, damit er dort zuerst funktioniert. Es wird alles für Sie einrichten. Sobald es dort funktioniert, kopieren Sie es in Ihre andere Umgebung und untersuchen Sie alle Probleme mit dieser Umgebung.


6

Der Fehler No provider for NameServiceist ein häufiges Problem, mit dem viele Angular2-Anfänger konfrontiert sind.

Grund : Bevor Sie einen benutzerdefinierten Dienst verwenden können, müssen Sie ihn zunächst bei NgModule registrieren, indem Sie ihn zur Anbieterliste hinzufügen:

Lösung:

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


4

Hallo, Sie können dies in Ihrer .ts-Datei verwenden:

Importieren Sie zuerst Ihren Dienst in diese .ts-Datei:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Dann können Sie in derselben Datei Folgendes hinzufügen providers: [Your_Service_Name]:

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

4

Fügen Sie es Anbietern hinzu, die nicht injizierbar sind

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

3

In Angular können Sie einen Dienst auf zwei Arten registrieren:

1. Registrieren Sie einen Dienst im Modul oder in der Stammkomponente

Auswirkungen:

  • Verfügbar in allen Komponenten
  • Verfügbar bei lebenslanger Anwendung

Sie sollten vorsichtig sein, wenn Sie einen Dienst in einem faul geladenen Modul registrieren:

  • Der Dienst ist nur für Komponenten verfügbar, die in diesem Modul deklariert sind

  • Der Dienst ist bei lebenslanger Anwendung nur verfügbar, wenn das Modul geladen ist

2. Registrieren Sie einen Dienst in einer anderen Anwendungskomponente

Auswirkungen:

  • Wird eine separate Instanz des Dienstes in die Komponente eingefügt

Sie sollten vorsichtig sein, wenn Sie einen Dienst in einer anderen Anwendungskomponente registrieren

  • Die Instanz des injizierten Dienstes ist nur für die Komponente und alle untergeordneten Komponenten verfügbar.

  • Die Instanz ist während der Lebensdauer der Komponente verfügbar.


2

Sie müssen es dem Provider-Array hinzufügen, das alle Abhängigkeiten von Ihrer Komponente enthält.

Schauen Sie sich diesen Abschnitt in der eckigen Dokumentation an:

Registrieren von Anbietern in einer Komponente

Hier ist eine überarbeitete HeroesComponent, die den HeroService in seinem Provider-Array registriert.

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 { }

Wann wird NgModule im Vergleich zu einer Anwendungskomponente verwendet?

Einerseits ist ein Anbieter in einem NgModule im Root-Injektor registriert. Das bedeutet, dass jeder in einem NgModule registrierte Anbieter in der gesamten Anwendung zugänglich ist.

Andererseits ist ein in einer Anwendungskomponente registrierter Anbieter nur für diese Komponente und alle ihre untergeordneten Komponenten verfügbar.

Hier muss der APP_CONFIG-Dienst in der gesamten Anwendung verfügbar sein, damit er im AppModule @ NgModule-Provider-Array registriert ist. Da der HeroService jedoch nur im Funktionsbereich Heroes und nirgendwo anders verwendet wird, ist es sinnvoll, ihn in der HeroesComponent zu registrieren.

Siehe auch "Soll ich dem Root-AppModule oder der Root-AppComponent app-weite Anbieter hinzufügen?" in den NgModule FAQ.

Ändern Sie in Ihrem Fall einfach die injizierbaren Elemente in Anbieter wie die folgenden:

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

Auch in den neuen Versionen von Angular sind @View und einige andere Sachen weg.

Weitere Informationen finden Sie hier .


2

Fügen Sie Ihren Dienst dem Array provider [] in der Datei app.module.ts hinzu. Wie unten

// hier ist mein Service CarService

app.module.ts

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

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

1

Bei Angular2 müssen Sie alle injizierbaren Dateien im Bootstrap-Funktionsaufruf deklarieren. Ohne dies ist Ihr Service kein injizierbares Objekt.

bootstrap(MyAppComponent,[NameService]);

1
Das ist nicht ganz richtig. Wir können den Dienst in bootstrap () oder in das providersArray im Konfigurationsobjekt der Komponente aufnehmen. Wenn es im providersArray enthalten ist, erhalten wir eine Instanz pro gebundener Komponente. Siehe die Hierarchical Injectors doc für weitere Informationen.
Mark Rajcok

Ja, wie von @MarkRajcok gesagt, bieten wir zum Zeitpunkt des Bootstraps nur die Dienste an, die wir in der gesamten App verwenden müssen. Auf diese Weise mussten wir nicht jedes Mal in den Provider injizieren, da dadurch eine Instanz für jede Komponente erstellt wird.
Pardeep Jain

1

Fügen Sie @Injectable zu Ihrem Service hinzu als:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

und fügen Sie in Ihrer Komponente die Anbieter hinzu als:

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

oder wenn Sie über die gesamte Anwendung auf Ihren Dienst zugreifen möchten, können Sie den App-Anbieter übergeben


1

Blockquote

Registrieren von Anbietern in einer Komponente

Hier ist eine überarbeitete HeroesComponent, die den HeroService in seinem Provider-Array registriert.

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.