Angular nenhum provedor para NameService

326

Estou com um problema ao carregar uma classe em um componente Angular. Eu tenho tentado resolvê-lo por um longo tempo; Eu até tentei juntar tudo isso em um único arquivo. O que eu tenho é:

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

Continuo recebendo uma mensagem de erro dizendo No provider for NameService.

Alguém pode me ajudar a identificar o problema com meu código?

M.Svrcek
fonte
6
a partir do Alpha 42: @Component ({provider: [NameService]})
timmz 16/10/2015

Respostas:

470

Você tem que usar em providersvez deinjectables

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

Exemplo de código completo aqui .

Klas Mellbourn
fonte
7
@unobf as declarações de importação não parecem quebradas para mim. A resposta anterior pode estar correta para os alfas mais antigos da biblioteca angular2. O guia original refere-se ao alfa-28, eu uso o alfa 35. Além disso, forneço um link para um exemplo de código completo, portanto, acho que forneci muitas informações.
Klas Mellbourn 31/08/2015
4
Uma atualização para futuros googlers: usar providerstrabalhos na versão beta mais recente (beta 0).
Nathanhleung
@nathanhleung tanto ligações e prestadores de trabalho - isso é temporário ou eles estão apenas fazendo o mesmo internamente
Simon_Weaver
@Simon_Weaver hmm eles podem ter mudado na versão beta mais recente - em beta.0 eu não poderia obtê-lo para trabalhar combindings
nathanhleung
1
e se o serviço for usado em outro serviço? eu o adicionei aos provedores de módulos que eu pensava que o disponibilizariam globalmente, mas ainda assim recebíamos esse erro #
Sonic Soul
79

No Angular 2, existem três lugares em que você pode "fornecer" serviços:

  1. bootstrap
  2. componente raiz
  3. outros componentes ou diretrizes

"A opção do provedor de auto-inicialização destina-se à configuração e substituição dos serviços pré-registrados da Angular, como seu suporte a roteamento." - referência

Se você deseja apenas uma instância do NameService em todo o aplicativo (por exemplo, Singleton), inclua-a na providersmatriz do componente raiz:

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

Plunker

Se você preferir ter uma instância por componente, use a providersmatriz no objeto de configuração do componente:

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

Consulte o documento Injetores hierárquicos para obter mais informações.

Mark Rajcok
fonte
4
Esta é uma resposta muito boa. Além disso, explica as diferenças entre declarar o serviço no componente raiz e declarar em outros componentes filhos.
Taf
34

A partir do Angular 2 Beta:

Adicione @Injectableao seu serviço como:

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

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

    getNames() {
        return this.names;
    }
}

e à sua configuração de componente, adicione o seguinte providers:

@Component({
    selector: 'my-app',
    providers: [NameService]
})
artesão
fonte
22

Você deve estar injetando NameServicedentro providersvariedade de seu AppModule's NgModulemetadados.

@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 você deseja criar uma Dependência para um determinado nível de componente sem se preocupar com o estado do seu aplicativo, pode injetar essa dependência na providersopção de metadados do componente, como a resposta aceita do @Klass mostrada.

Pankaj Parkar
fonte
Tentei adicionar um serviço em app.module.shared.ts na seção @NgModule: provider: [DataManagerService], mas ainda assim recebo o erro: Erro: nenhum provedor para DataManagerService!
Paul
1
@Paul, você está injetando seu serviço no módulo correto? e DataManagerServicetem @Injectabledecorador sobre ele?
Pankaj Parkar
15

Surpreendentemente, a sintaxe mudou mais uma vez na versão mais recente do Angular :-) Dos documentos do Angular 6 :

A partir do Angular 6.0, a maneira preferida de criar um serviço singleton é especificar no serviço que ele deve ser fornecido na raiz do aplicativo. Isso é feito configurando a opção fornecidoIn como root no decorador @Injectable do serviço:

src / app / user.service.0.ts

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

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

Você deve injetar NameService na matriz de provedores dos metadados NgModule do AppModule.

@NgModule({
   providers: [MyService]
})

e certifique-se de importar seu componente pelo mesmo nome (diferencia maiúsculas de minúsculas), pois SystemJs diferencia maiúsculas de minúsculas (por design). Se você usar um nome de caminho diferente nos arquivos do seu projeto, como este:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

o System js fará importações duplas

saghar.fadaei
fonte
1
Excelente! Ao usar barris para agrupar importações, encontrei esse erro. Sua dica SystemJS me ajudou :)
Jony Adamit
12

No Angular v2 e acima, é agora:

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

supercobra
fonte
7

O Angular 2 mudou. Aqui está a aparência da parte superior do seu código:

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

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

Além disso, convém usar getters e setters em seu serviço:

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

Em seu aplicativo, você pode simplesmente:

this.names = nameService.names;

Sugiro que você vá ao plnkr.co e crie um novo plunk Angular 2 (ES6) e faça com que ele funcione primeiro. Isso configurará tudo para você. Quando estiver funcionando, copie-o para o seu outro ambiente e trie todos os problemas desse ambiente.

unobf
fonte
6

O erro No provider for NameServiceé um problema comum que muitos iniciantes do Angular2 enfrentam.

Motivo : antes de usar qualquer serviço personalizado, primeiro é necessário registrá-lo no NgModule, adicionando-o à lista de provedores:

Solução:

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

Olá, Você pode usar isso no seu arquivo .ts:

primeiro importe seu serviço neste arquivo .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Em seguida, no mesmo arquivo, você pode adicionar providers: [Your_Service_Name]:

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

Adicione a provedores não injetáveis

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

No Angular, você pode registrar um serviço de duas maneiras:

1. Registre um serviço no módulo ou componente raiz

Efeitos:

  • Disponível em todos os componentes
  • Disponível na aplicação vitalícia

Você deve tomar cuidado ao registrar um serviço em um módulo carregado lento:

  • O serviço está disponível apenas em componentes declarados nesse módulo

  • O serviço estará disponível no aplicativo vitalício apenas quando o módulo for carregado

2. Registre um serviço em qualquer outro componente de aplicativo

Efeitos:

  • Será injetada uma instância separada do Serviço no componente

Você deve tomar cuidado se registrar um serviço em qualquer outro componente do aplicativo

  • A instância do serviço injetado estará disponível apenas no componente e em todos os seus filhos.

  • A instância estará disponível no tempo de vida do componente.

Rzv Razvan
fonte
2

Você precisa adicioná-lo à matriz de fornecedores, que inclui toda a dependência do seu componente.

Veja esta seção na documentação angular:

Registrando provedores em um componente

Aqui está um HeroesComponent revisado que registra o HeroService em sua matriz de provedores.

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 usar o NgModule versus um componente de aplicativo

Por um lado, um provedor em um NgModule é registrado no injetor raiz. Isso significa que todos os provedores registrados em um NgModule estarão acessíveis em todo o aplicativo.

Por outro lado, um provedor registrado em um componente de aplicativo está disponível apenas nesse componente e em todos os seus filhos.

Aqui, o serviço APP_CONFIG precisa estar disponível em todo o aplicativo, portanto, é registrado na matriz de provedores AppModule @NgModule. Mas como o HeroService é usado apenas na área de recursos Heroes e em nenhum outro lugar, faz sentido registrá-lo no HeroesComponent.

Consulte também "Devo adicionar provedores de todo o aplicativo ao AppModule raiz ou ao AppComponent raiz?" no FAQ do NgModule.

Portanto, no seu caso, basta alterar os injetáveis ​​para fornecedores como abaixo:

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

Também nas novas versões do Angular, o @View e alguns outros itens já foram.

Para mais informações, visite aqui .

Alireza
fonte
2

adicione seu serviço à matriz de provedores [] no arquivo app.module.ts. Como abaixo

// aqui meu serviço é CarService

app.module.ts

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

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

Angular2 requer que você declare todos os injetáveis ​​na chamada de função de inicialização. Sem isso, seu serviço não é um objeto injetável.

bootstrap(MyAppComponent,[NameService]);
preet0982
fonte
1
isto não está correto. Podemos incluir o serviço em bootstrap () ou na providersmatriz no objeto de configuração do componente. Se estiver incluído na providersmatriz, obteremos uma instância por componente vinculado. Consulte o documento Injetores hierárquicos para obter mais informações.
Mark Rajcok
sim, como dito por @MarkRajcok, também fornecemos apenas os serviços no momento da inicialização que precisamos usar em todo o aplicativo. ao fazer isso, não precisamos injetar todas as vezes no provedor, pois ele criará uma instância para todos os componentes.
Pardeep Jain
1

Adicione @Injectable ao seu serviço como:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

e no seu componente adicione os provedores como:

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

ou se você deseja acessar seu serviço em todo o aplicativo, pode passar no provedor de aplicativos

sachinkasana
fonte
1

Bloco de citação

Registrando provedores em um componente

Aqui está um HeroesComponent revisado que registra o HeroService em sua matriz de provedores.

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

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

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