Aucun fournisseur angulaire pour NameService

326

J'ai un problème lors du chargement d'une classe dans un composant angulaire. J'essaie de le résoudre depuis longtemps; J'ai même essayé de tout joindre dans un seul fichier. Ce que j'ai c'est:

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

Je reçois toujours un message d'erreur No provider for NameService.

Quelqu'un peut-il m'aider à détecter le problème avec mon code?

M.Svrcek
la source
6
à partir d'Alpha 42: @Component ({providers: [NameService]})
timmz

Réponses:

470

Vous devez utiliser providersau lieu deinjectables

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

Exemple de code complet ici .

Klas Mellbourn
la source
7
@unobf les instructions d'importation ne me semblent pas rompues. La réponse précédente pourrait bien être correcte pour les anciens alphas de la bibliothèque angular2. Le guide original se réfère à alpha-28, j'utilise alpha 35. De plus, je fournis un lien vers un exemple de code complet, donc je pense avoir fourni beaucoup d'informations.
Klas Mellbourn
4
Une mise à jour pour les futurs googleurs: utilisation des providerstravaux sur la dernière version bêta (beta 0).
nathanhleung
@nathanhleung les liaisons et les fournisseurs fonctionnent - est-ce temporaire ou font-ils simplement la même chose en interne
Simon_Weaver
@Simon_Weaver hmm ils l'ont peut-être changé dans la dernière version bêta - en version bêta.0 Je ne pouvais pas le faire fonctionnerbindings
nathanhleung
1
que faire si le service est utilisé à partir d'un autre service? je l'ai ajouté aux fournisseurs de modules qui, je le pensais, le rendraient disponible dans le monde entier, mais obtenant toujours cette erreur
Sonic Soul
79

Dans Angular 2, vous pouvez "fournir" trois services:

  1. amorcer
  2. composant racine
  3. autres composants ou directives

"L'option du fournisseur d'amorçage est conçue pour configurer et remplacer les propres services préenregistrés d'Angular, tels que sa prise en charge du routage." - référence

Si vous ne souhaitez qu'une seule instance de NameService sur l'ensemble de votre application (c.-à-d. Singleton), incluez-la dans le providerstableau de votre composant racine:

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

Plunker

Si vous préférez avoir une instance par composant, utilisez plutôt le providerstableau dans l'objet de configuration du composant:

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

Consultez le document Injecteurs hiérarchiques pour plus d'informations.

Mark Rajcok
la source
4
C'est une très bonne réponse. Il explique en outre les différences entre déclarer le service dans le composant racine et déclarer dans d'autres composants enfants.
Taf
34

Depuis Angular 2 Beta:

Ajoutez @Injectableà votre service en tant que:

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

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

    getNames() {
        return this.names;
    }
}

et à votre configuration de composant, ajoutez le providerscomme:

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

Vous devriez injectez à l' NameServiceintérieur de providerstableau de votre AppModulede » NgModulemétadonnées.

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

}

Si vous souhaitez créer une dépendance pour un niveau de composant particulier sans vous soucier de l'état de votre application, vous pouvez injecter cette dépendance sur l' providersoption de métadonnées de composant comme la réponse @Klass acceptée illustrée.

Pankaj Parkar
la source
J'ai essayé d'ajouter un service dans app.module.shared.ts dans la section @NgModule: fournisseurs: [DataManagerService] mais j'obtiens toujours l'erreur: Erreur: Aucun fournisseur pour DataManagerService!
Paul
1
@Paul injectez-vous votre service dans le bon module? et DataManagerServiceest-ce que le @Injectabledécorateur est dessus?
Pankaj Parkar
15

Étonnamment, la syntaxe a encore changé dans la dernière version d'Angular :-) Depuis les documents d' Angular 6 :

À partir d'Angular 6.0, la façon préférée de créer un service singleton est de spécifier sur le service qu'il doit être fourni à la racine de l'application. Cela se fait en définissant providedIn à root sur le décorateur @Injectable du service:

src / app / user.service.0.ts

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

@Injectable({
  providedIn: 'root',
})
export class UserService {
}
Derrick Miller
la source
14

Vous devez injecter NameService dans le tableau des fournisseurs de métadonnées NgModule de votre AppModule.

@NgModule({
   providers: [MyService]
})

et assurez-vous d'importer dans votre composant par le même nom (sensible à la casse), car SystemJs est sensible à la casse (par conception). Si vous utilisez un nom de chemin différent dans vos fichiers de projet comme ceci:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

alors le système js fera des doubles importations

saghar.fadaei
la source
1
Excellent! Lors de l'utilisation de barils pour regrouper les importations, j'ai rencontré cette erreur. Votre conseil SystemJS m'a aidé :)
Jony Adamit
12

Dans Angular v2 et plus, c'est maintenant:

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

supercobra
la source
7

Angular 2 a changé, voici à quoi devrait ressembler le haut de votre code:

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

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

Vous pouvez également utiliser des getters et setters à votre service:

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

Ensuite, dans votre application, vous pouvez simplement faire:

this.names = nameService.names;

Je vous suggère d'aller sur plnkr.co et de créer un nouveau plunk Angular 2 (ES6) et de le faire fonctionner en premier. Il mettra tout en place pour vous. Une fois que cela fonctionne, copiez-le dans votre autre environnement et triez tous les problèmes avec cet environnement.

unobf
la source
6

L'erreur No provider for NameServiceest un problème commun auquel de nombreux débutants Angular2 sont confrontés.

Raison : Avant d'utiliser un service personnalisé, vous devez d'abord l'enregistrer auprès de NgModule en l'ajoutant à la liste des fournisseurs:

Solution:

@NgModule({
    imports: [...],
    providers: [CustomServiceName]
})
Suneet Bansal
la source
4

Bonjour, vous pouvez utiliser ceci dans votre fichier .ts:

Importez d'abord votre service dans ce fichier .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Ensuite, dans le même fichier, vous pouvez ajouter providers: [Your_Service_Name]:

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

Ajoutez-le aux fournisseurs non injectables

@Component({
    selector:'my-app',
    providers: [NameService]
})
Gopinath Kaliappan
la source
3

Dans Angular, vous pouvez enregistrer un service de deux manières:

1. Enregistrer un service dans le module ou le composant racine

Effets:

  • Disponible dans tous les composants
  • Disponible sur demande à vie

Vous devez faire attention si vous enregistrez un service dans un module chargé paresseusement:

  • Le service est disponible uniquement dans les composants déclarés dans ce module

  • Le service sera disponible sur l'application à vie uniquement lorsque le module est chargé

2. Enregistrez un service dans tout autre composant d'application

Effets:

  • Sera injecté une instance distincte du Service dans le composant

Vous devez faire attention si vous enregistrez un service dans un autre composant d'application

  • L'instance du service injecté sera disponible uniquement dans le composant et tous ses enfants.

  • L'instance sera disponible sur la durée de vie du composant.

Rzv Razvan
la source
2

Vous devez l'ajouter au tableau des fournisseurs, qui inclut toutes les dépendances de votre composant.

Regardez cette section dans la documentation angulaire:

Enregistrement de fournisseurs dans un composant

Voici un HeroesComponent révisé qui enregistre le HeroService dans son tableau de fournisseurs.

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

Quand utiliser NgModule par rapport à un composant d'application

D'une part, un fournisseur d'un NgModule est enregistré dans l'injecteur racine. Cela signifie que chaque fournisseur enregistré dans un NgModule sera accessible dans toute l'application.

En revanche, un fournisseur enregistré dans un composant d'application n'est disponible que sur ce composant et tous ses enfants.

Ici, le service APP_CONFIG doit être disponible dans toute l'application, il est donc enregistré dans le tableau des fournisseurs AppModule @NgModule. Mais comme HeroService n'est utilisé que dans la zone de fonctionnalité Heroes et nulle part ailleurs, il est logique de l'enregistrer dans HeroesComponent.

Voir également "Dois-je ajouter des fournisseurs à l'échelle de l'application à l'AppModule racine ou à l'AppComponent racine?" dans la FAQ NgModule.

Donc, dans votre cas, changez simplement les injectables en fournisseurs comme ci-dessous:

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

Également dans les nouvelles versions d'Angular, @View et d'autres éléments disparus.

Pour plus d'informations, visitez ici .

Alireza
la source
2

ajoutez votre service au tableau de fournisseurs [] dans le fichier app.module.ts. Comme ci-dessous

// ici mon service est CarService

app.module.ts

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

providers: [CarsService] // you can include as many services you have 
Surendra Parchuru
la source
1

Angular2 vous oblige à déclarer tous les injectables dans l'appel de fonction bootstrap. Sans cela, votre service n'est pas un objet injectable.

bootstrap(MyAppComponent,[NameService]);
preet0982
la source
1
Ce n'est pas tout à fait correct. Nous pouvons inclure le service dans bootstrap (), ou dans le providerstableau dans l'objet de configuration du composant. S'il est inclus dans le providerstableau, nous obtenons une instance par composant lié. Consultez le document Injecteurs hiérarchiques pour plus d'informations.
Mark Rajcok
oui, comme l'a dit @MarkRajcok, nous ne fournissons que les services au moment du bootstrap que nous devons utiliser dans toute l'application. ce faisant, nous n'avons pas eu besoin d'injecter à chaque fois dans le fournisseur, car cela créera une instance pour chaque composant.
Pardeep Jain
1

Ajoutez @Injectable à votre service en tant que:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

et dans votre composant, ajoutez les fournisseurs en tant que:

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

ou si vous souhaitez accéder à votre service dans toute l'application, vous pouvez passer au fournisseur d'application

sachinkasana
la source
1

Blockquote

Enregistrement de fournisseurs dans un composant

Voici un HeroesComponent révisé qui enregistre le HeroService dans son tableau de fournisseurs.

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Chanaka Weerasinghe
la source