Angular sin proveedor para NameService


326

Tengo un problema al cargar una clase en un componente angular. He estado tratando de resolverlo por mucho tiempo; Incluso he intentado unirlo todo en un solo archivo. Lo que tengo es:

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

servicios / NameService.ts

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

Sigo recibiendo un mensaje de error que dice No provider for NameService.

¿Alguien puede ayudarme a detectar el problema con mi código?


66
a partir de Alpha 42: @Component ({proveedores: [NameService]})
timmz

Respuestas:


470

Tienes que usar en providerslugar deinjectables

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

Ejemplo de código completo aquí .


77
@unobf las declaraciones de importación no me parecen rotas. La respuesta anterior puede ser correcta para los alfa antiguos de la biblioteca angular2. La guía original se refiere a alpha-28, yo uso alpha 35. Además, proporciono un enlace a un ejemplo de código completo, así que creo que he proporcionado mucha información.
Klas Mellbourn

44
Una actualización para futuros googlers: usar providerstrabajos en la última versión beta (beta 0).
nathanhleung

@nathanhleung funcionan tanto los enlaces como los proveedores, ¿es temporal o simplemente están haciendo lo mismo internamente
Simon_Weaver

@Simon_Weaver hmm pueden haberlo cambiado en la última versión beta - en beta.0 No pude hacerlo funcionarbindings
nathanhleung

1
¿Qué pasa si el servicio se utiliza desde otro servicio? Lo agregué a los proveedores de módulos que pensé que lo haría disponible a nivel mundial, pero aún obteniendo ese error
Sonic Soul

79

En Angular 2 hay tres lugares donde puede "proporcionar" servicios:

  1. oreja
  2. componente raíz
  3. otros componentes o directivas

"La opción del proveedor de bootstrap está diseñada para configurar y anular los servicios prerregistrados de Angular, como su soporte de enrutamiento". - referencia

Si solo desea una instancia de NameService en toda su aplicación (es decir, Singleton), inclúyala en la providersmatriz de su componente raíz:

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

Plunker

Si prefiere tener una instancia por componente, use la providersmatriz en el objeto de configuración del componente:

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

Consulte el documento de Inyectores jerárquicos para obtener más información.


44
Esta es una muy buena respuesta. Explica además las diferencias entre declarar el servicio en el componente raíz y declarar en otros componentes secundarios.
Taf

34

A partir de Angular 2 Beta:

Agregar @Injectablea su servicio como:

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

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

    getNames() {
        return this.names;
    }
}

y a la configuración de su componente agregue el providerscomo:

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

22

Usted debe a inyectar NameServicedentro de providersgama de su AppModule's NgModulemetadatos.

@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 desea crear una dependencia para un nivel de componente particular sin preocuparse por el estado de su aplicación, puede inyectar esa dependencia en la providersopción de metadatos del componente como se muestra en la respuesta @Klass aceptada .


Intenté agregar un servicio en app.module.shared.ts en la sección @NgModule: proveedores: [DataManagerService] pero aún recibo el error: Error: ¡No hay proveedor para DataManagerService!
Paul

1
@Paul, ¿estás inyectando tu servicio en el módulo correcto? y DataManagerServicetiene @Injectabledecorador encima?
Pankaj Parkar

15

Sorprendentemente, la sintaxis ha cambiado una vez más en la última versión de Angular :-) De los documentos de Angular 6 :

A partir de Angular 6.0, la forma preferida de crear un servicio singleton es especificar en el servicio que se debe proporcionar en la raíz de la aplicación. Esto se hace estableciendo provideIn en root en el decorador @Injectable del servicio:

src / app / user.service.0.ts

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

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

14

Debería inyectar NameService dentro de la matriz de proveedores de los metadatos NgModule de su AppModule.

@NgModule({
   providers: [MyService]
})

y asegúrese de importar en su componente por el mismo nombre (distingue entre mayúsculas y minúsculas), porque SystemJs distingue entre mayúsculas y minúsculas (por diseño). Si usa un nombre de ruta diferente en sus archivos de proyecto de esta manera:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

entonces el sistema js hará importaciones dobles


1
¡Excelente! Al usar barriles para agrupar importaciones, encontré este error. Tu consejo de SystemJS me ayudó :)
Jony Adamit

12

En Angular v2 y hasta ahora es:

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


7

Angular 2 ha cambiado, así es como debería verse la parte superior de su código:

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

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

Además, es posible que desee utilizar getters y setters en su servicio:

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

Luego, en su aplicación, simplemente puede hacer:

this.names = nameService.names;

Le sugiero que vaya a plnkr.co y cree un nuevo plunk Angular 2 (ES6) y que primero funcione allí. Configurará todo para ti. Una vez que esté funcionando allí, cópielo en su otro entorno y clasifique cualquier problema con ese entorno.


6

El error No provider for NameServicees un problema común que enfrentan muchos principiantes de Angular2.

Motivo : antes de utilizar cualquier servicio personalizado, primero debe registrarlo en NgModule agregándolo a la lista de proveedores:

Solución:

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


4

Hola, puedes usar esto en tu archivo .ts:

Primero importe su servicio en este archivo .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Luego, en el mismo archivo, puede agregar providers: [Your_Service_Name]:

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

4

Agréguelo a proveedores no inyectables

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

3

En Angular puede registrar un servicio de dos maneras:

1. Registre un servicio en el módulo o componente raíz

Efectos:

  • Disponible en todos los componentes
  • Disponible en aplicación de por vida

Debe tener cuidado si registra un servicio en un módulo con carga lenta:

  • El servicio solo está disponible en componentes declarados en ese módulo

  • El servicio estará disponible en la aplicación de por vida solo cuando se cargue el módulo

2. Registre un servicio en cualquier otro componente de la aplicación.

Efectos:

  • Se inyectará una instancia separada del Servicio en el componente

Debe tener cuidado si registra un servicio en cualquier otro componente de la aplicación

  • La instancia del servicio inyectado estará disponible solo en el componente y todos sus elementos secundarios.

  • La instancia estará disponible en la vida útil del componente.


2

Debe agregarlo a la matriz de proveedores, que incluye toda la dependencia de su componente.

Mire esta sección en la documentación angular:

Registrar proveedores en un componente

Aquí hay un HeroesComponent revisado que registra HeroService en su matriz de proveedores.

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

Cuándo usar NgModule versus un componente de aplicación

Por un lado, un proveedor en un NgModule está registrado en el inyector raíz. Eso significa que todos los proveedores registrados dentro de un NgModule serán accesibles en toda la aplicación.

Por otro lado, un proveedor registrado en un componente de aplicación está disponible solo en ese componente y todos sus hijos.

Aquí, el servicio APP_CONFIG debe estar disponible en toda la aplicación, por lo que está registrado en la matriz de proveedores AppModule @NgModule. Pero dado que HeroService solo se usa dentro del área de características de Héroes y en ningún otro lugar, tiene sentido registrarlo en el Componente de Héroes.

Consulte también "¿Debo agregar proveedores de toda la aplicación al AppModule raíz o al AppComponent raíz?" en las preguntas frecuentes de NgModule.

Entonces, en su caso, simplemente cambie los inyectables a proveedores como a continuación:

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

También en las nuevas versiones de Angular, @View y algunas otras cosas desaparecidas.

Para más información, visite aquí .


2

agregue su servicio a la matriz de proveedores [] en el archivo app.module.ts. Como abajo

// aquí mi servicio es CarService

app.module.ts

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

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

1

Angular2 requiere que declare todos los inyectables en la llamada de función bootstrap. Sin esto, su servicio no es un objeto inyectable.

bootstrap(MyAppComponent,[NameService]);

1
Esto no es muy correcto. Podemos incluir el servicio en bootstrap () o en la providersmatriz en el objeto de configuración del componente. Si se incluye en la providersmatriz, obtenemos una instancia por componente enlazado. Consulte el documento de Inyectores jerárquicos para obtener más información.
Mark Rajcok

Sí, como dijo @MarkRajcok, también proporcionamos solo aquellos servicios en el momento del arranque, cuáles tenemos que usar en toda la aplicación. al hacerlo, no necesitamos inyectar cada vez en el proveedor porque creará una instancia para cada componente.
Pardeep Jain

1

Agregue @Injectable a su servicio como:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

y en su componente agregue los proveedores como:

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

o si desea acceder a su servicio en toda la aplicación, puede pasar al proveedor


1

Blockquote

Registrar proveedores en un componente

Aquí hay un HeroesComponent revisado que registra HeroService en su matriz de proveedores.

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.