Nessun fornitore angolare per NameService


326

Ho un problema con il caricamento di una classe in un componente angolare. Ho cercato di risolverlo da molto tempo; Ho anche provato a unirmi a tutto in un unico file. Quello che ho è:

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

servizi / NameService.ts

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

Continuo a ricevere un messaggio di errore che dice No provider for NameService.

Qualcuno può aiutarmi a individuare il problema con il mio codice?


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

Risposte:


470

Devi usare providersinvece diinjectables

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

Esempio di codice completo qui .


7
@unobf le dichiarazioni di importazione non mi sembrano rotte. La risposta precedente potrebbe essere corretta per gli alfa più vecchi della libreria angular2. La guida originale fa riferimento a alpha-28, io uso alpha 35. Inoltre, fornisco un collegamento a un esempio di codice completo, quindi penso di aver fornito molte informazioni.
Klas Mellbourn,

4
Un aggiornamento per futuri googler: usare le providersopere sull'ultima beta (beta 0).
nathanhleung,

@nathanhleung funziona sia i binding che i provider - è temporaneo o stanno semplicemente facendo lo stesso internamente
Simon_Weaver

@Simon_Weaver hmm potrebbero averlo cambiato nell'ultima beta - in beta.0 non sono riuscito a farlo funzionarebindings
nathanhleung

1
cosa succede se il servizio viene utilizzato da un altro servizio? l'ho aggiunto ai fornitori di moduli che pensavo l'avrebbero reso disponibile a livello globale, ma continuavo a ricevere quell'errore
Sonic Soul

79

In Angular 2 ci sono tre posti in cui puoi "fornire" servizi:

  1. bootstrap
  2. componente radice
  3. altri componenti o direttive

"L'opzione del fornitore bootstrap è progettata per configurare e sovrascrivere i servizi preregistrati di Angular, come il suo supporto di routing." - riferimento

Se desideri solo un'istanza di NameService nell'intera app (ad es. Singleton), includila providersnell'array del componente radice:

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

Plunker

Se preferisci avere un'istanza per componente, utilizza invece l' providersarray nell'oggetto di configurazione del componente:

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

Consulta il documento Iniettori gerarchici per maggiori informazioni.


4
Questa è davvero una buona risposta Spiega inoltre le differenze tra la dichiarazione del servizio nel componente radice rispetto alla dichiarazione in altri componenti figlio.
Taf

34

A partire da Angular 2 Beta:

Aggiungi @Injectableal tuo servizio come:

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

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

    getNames() {
        return this.names;
    }
}

e alla configurazione del tuo componente aggiungi providerscome:

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

22

Si dovrebbe essere iniettando NameServiceall'interno providersgamma di vostra AppModule's NgModulemetadati.

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

}

Se si desidera creare una dipendenza per un determinato livello di componente senza preoccuparsi dello stato dell'applicazione, è possibile iniettare quella dipendenza providersdall'opzione metadati del componente come la risposta accettata @Klass mostrata.


Ho provato ad aggiungere un servizio in app.module.shared.ts nella sezione @NgModule: provider: [DataManagerService] ma ottengo ancora l'errore: Errore: nessun provider per DataManagerService!
Paolo,

1
@Paul stai iniettando il tuo servizio nel modulo corretto? e DataManagerServiceha il @Injectabledecoratore sopra?
Pankaj Parkar,

15

Incredibilmente, la sintassi è cambiata ancora una volta nell'ultima versione di Angular :-) Dai documenti di Angular 6 :

A partire da Angular 6.0, il modo preferito per creare un servizio singleton è specificare sul servizio che dovrebbe essere fornito nella radice dell'applicazione. Questo viene fatto impostando fornitoIn a root sul decoratore @Injectable del servizio:

src / app / user.service.0.ts

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

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

14

Dovresti iniettare NameService all'interno dell'array provider dei metadati NgModule di AppModule.

@NgModule({
   providers: [MyService]
})

e assicurati di importare nel tuo componente con lo stesso nome (distinzione tra maiuscole e minuscole), poiché SystemJs distingue tra maiuscole e minuscole (in base alla progettazione). Se si utilizza un nome percorso diverso nei file di progetto in questo modo:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

quindi System js effettuerà doppie importazioni


1
Eccellente! Quando ho usato i barili per raggruppare le importazioni ho riscontrato questo errore. Il tuo consiglio SystemJS mi ha aiutato :)
Jony Adamit, il

12

In Angular v2 e versioni successive è ora:

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


7

Angular 2 è cambiato, ecco come dovrebbe apparire la parte superiore del codice:

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

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

Inoltre, potresti voler utilizzare getter e setter nel tuo servizio:

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

Quindi nella tua app puoi semplicemente fare:

this.names = nameService.names;

Ti suggerisco di andare su plnkr.co e creare un nuovo trunk Angular 2 (ES6) e farlo funzionare prima. Ti preparerà tutto. Una volta che funziona lì, copiarlo nell'altro ambiente e valutare eventuali problemi con quell'ambiente.


6

L'errore No provider for NameServiceè un problema comune che devono affrontare molti principianti di Angular2.

Motivo : prima di utilizzare qualsiasi servizio personalizzato è necessario prima registrarlo con NgModule aggiungendolo all'elenco dei provider:

Soluzione:

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


4

Ciao, puoi usarlo nel tuo file .ts:

prima importa il tuo servizio in questo file .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Quindi nello stesso file è possibile aggiungere providers: [Your_Service_Name]:

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

4

Aggiungilo a provider non iniettabili

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

3

In Angular puoi registrare un servizio in due modi:

1. Registrare un servizio nel modulo o nel componente radice

effetti:

  • Disponibile in tutti i componenti
  • Disponibile su applicazione a vita

Prestare attenzione se si registra un servizio in un modulo caricato in modo pigro:

  • Il servizio è disponibile solo nei componenti dichiarati in quel modulo

  • Il servizio sarà disponibile sull'applicazione a vita solo quando il modulo è caricato

2. Registrare un servizio in qualsiasi altro componente dell'applicazione

effetti:

  • Verrà iniettata un'istanza separata del servizio nel componente

Prestare attenzione se si registra un servizio in qualsiasi altro componente dell'applicazione

  • L'istanza del servizio iniettato sarà disponibile solo nel componente e in tutti i suoi figli.

  • L'istanza sarà disponibile durante la vita del componente.


2

È necessario aggiungerlo all'array provider, che include tutta la dipendenza dal componente.

Guarda questa sezione nella documentazione angolare:

Registrazione dei provider in un componente

Ecco un componente Heroes rivisto che registra HeroService nel suo array di provider.

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

Quando utilizzare NgModule rispetto a un componente dell'applicazione

Da un lato, un provider in un NgModule è registrato nell'iniettore di root. Ciò significa che tutti i provider registrati in un NgModule saranno accessibili nell'intera applicazione.

D'altra parte, un provider registrato in un componente dell'applicazione è disponibile solo su quel componente e su tutti i suoi figli.

Qui, il servizio APP_CONFIG deve essere disponibile in tutta l'applicazione, quindi è registrato nell'array dei provider AppModule @NgModule. Ma poiché HeroService viene utilizzato solo nell'area delle funzionalità di Heroes e in nessun altro luogo, ha senso registrarlo nel componente Heroes.

Vedi anche "Devo aggiungere provider a livello di app al modulo App root o al componente App root?" nelle FAQ di NgModule.

Quindi, nel tuo caso, cambia semplicemente iniettabili in provider come di seguito:

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

Anche nelle nuove versioni di Angular, @View e alcune altre cose scomparse.

Per maggiori informazioni, visita qui .


2

aggiungi il tuo servizio all'array provider [] nel file app.module.ts. Come sotto

// qui il mio servizio è CarService

app.module.ts

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

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

1

Angular2 richiede di dichiarare tutti gli iniettabili nella chiamata della funzione bootstrap. Senza questo il tuo servizio non è un oggetto iniettabile.

bootstrap(MyAppComponent,[NameService]);

1
Questo non è del tutto corretto. Possiamo includere il servizio in bootstrap () o providersnell'array nell'oggetto di configurazione del componente. Se è incluso providersnell'array, otteniamo un'istanza per componente associato. Vedi il documento Iniettori gerarchici per maggiori informazioni.
Mark Rajcok,

sì, come detto da @MarkRajcok, al momento del bootstrap forniamo solo quei servizi che dobbiamo usare nell'intera app. così facendo non abbiamo dovuto iniettare ogni volta nel provider perché creerà istanza per ogni componente.
Pardeep Jain,

1

Aggiungi @Injectable al tuo servizio come:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

e nel tuo componente aggiungi i provider come:

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

o se desideri accedere al tuo servizio in tutta l'applicazione, puoi passare al provider di app


1

blockquote

Registrazione dei provider in un componente

Ecco un componente Heroes rivisto che registra HeroService nel suo array di provider.

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.