Угловой нет поставщика для NameService

176

У меня проблема с загрузкой класса в компонент Angular. Я пытаюсь решить долгое время, даже пытался добавить его в один файл. У меня есть:

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

услуги /NameService.ts

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

Все время появляется сообщение об ошибке "Нет провайдера для NameService"...

Может кто-нибудь помочь мне определить эту небольшую проблему с моим кодом?

  • 5
    по состоянию на Альфа 42: @Component ({провайдеры: [NameService]})
Теги:
angular
systemjs

15 ответов

276
Лучший ответ

Вы должны использовать providers вместо injectables

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

Полный образец кода здесь.

  • 3
    Этот ответ не включает изменения, необходимые для исправления операторов импорта, которые не работают. Кроме того, почему вы не просто обновили существующий ответ, который был принят 1 июня (когда был задан вопрос), вместо того, чтобы создать частичный новый ответ?
  • 6
    @unobf операторы импорта не выглядят сломленными для меня. Предыдущий ответ вполне может быть правильным для более старых альфа-версий библиотеки angular2. Оригинальное руководство относится к альфа-28, я использую альфа-35. Кроме того, я предоставляю ссылку на полный пример кода, поэтому я думаю, что предоставил довольно много информации.
Показать ещё 6 комментариев
47

В Angular 2 есть три места, которые вы можете "предоставить":

  • самозагрузки
  • корневой компонент
  • другие компоненты или директивы

"Опция поставщика бутстрапов предназначена для настройки и переопределения Angular собственных предварительно зарегистрированных сервисов, таких как поддержка маршрутизации". - ссылка

Если вам нужен только один экземпляр NameService для всего вашего приложения (т.е. Singleton), включите его в массив providers вашего корневого компонента:

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

Plunker

Если вы предпочитаете использовать один экземпляр для каждого компонента, используйте массив providers в объекте конфигурации компонента:

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

Подробнее см. Иерархические инжекторы для получения дополнительной информации.

  • 4
    Это действительно хороший ответ. Далее объясняются различия между объявлением службы в корневом компоненте и объявлением в других дочерних компонентах.
24

По состоянию на Angular 2 Бета:

Добавьте @Injectable к вашему сервису как:

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

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

    getNames() {
        return this.names;
    }
}

и в конфигурацию вашего компонента добавьте providers как:

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

Вам следует ввести NameService внутри providers массив ваших метаданных AppModule NgModule.

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

}

Если вы хотите создать зависимость для определенного уровня компонента, не беспокоясь о состоянии своего приложения, вы можете ввести эту зависимость от компонента метаданных компонента providers, как принято @Klass показан ответ.

  • 0
    Я пытался добавить службу в app.module.shared.ts в разделе @NgModule: поставщики: [DataManagerService], но все равно получаю сообщение об ошибке: Ошибка: Нет поставщика для DataManagerService!
  • 1
    @ Пол, вы вводите свой сервис в правильном модуле? и имеет ли DataManagerService декоратор @Injectable поверх него?
8

Вы должны вводить NameService внутри массива поставщиков ваших метаданных AppModule NgModule.

@NgModule({
   providers: [MyService]
})

и убедитесь, что импорт в вашем компоненте с одинаковым именем (с учетом регистра), потому что SystemJs чувствителен к регистру (по дизайну). Если вы используете другое имя пути в файлах проекта, например:

main.module.ts

import { MyService } from './MyService';

ваш-component.ts

import { MyService } from './MyService';

то System js сделает двойной импорт

  • 1
    Отлично! При использовании стволов для группового импорта я столкнулся с этой ошибкой. Ваш совет SystemJS помог мне :)
6

В Angular v2 и выше:

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

6

Angular 2 изменилось, вот что должно выглядеть сверху вашего кода:

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

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

Кроме того, вы можете использовать геттеры и сеттеры в своем сервисе:

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

Затем в вашем приложении вы можете просто:

this.names = nameService.names;

Я предлагаю вам перейти на plnkr.co и создать новый Angular 2 (ES6) планшет и заставить его работать там первым. Он все устроит для вас. После того, как он работает там, скопируйте его в другую среду и разделите все проблемы с этой средой.

5

Вы также можете иметь зависимости, объявленные в команде bootstrap, например:

bootstrap(MyAppComponent,[NameService]);

По крайней мере, то, что сработало для меня в альфа40.

это ссылка: http://www.syntaxsuccess.com/viewarticle/dependency-injection-in-angular-2.0

3

Нет провайдера для NameService - распространенная проблема, которая приходит с новичком Angular2.

Причина: Прежде чем использовать какой-либо пользовательский сервис, мы должны сначала зарегистрировать его с помощью NgModule, добавив его в список поставщиков:

Решение:

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

Добавьте его к провайдерам не для инъекций

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

Привет, вы можете использовать это в своем файле .ts:

сначала импортируйте свою службу в этот файл .ts:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Затем в том же файле вы можете добавить providers: [Your_Service_Name]:

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

Вам нужно добавить его в массив поставщиков, который включает все параметры вашего компонента.

Посмотрите на этот раздел в документации angular:

Регистрация поставщиков в компоненте

Здесь пересмотренный HeroesComponent, который регистрирует HeroService в своем поставщиков.

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

Когда использовать NgModule и компонент приложения

С одной стороны, провайдер в NgModule зарегистрирован в корне инжектор. Это означает, что каждый провайдер, зарегистрированный в NgModule будут доступны во всем приложении.

С другой стороны, поставщик, зарегистрированный в прикладном компоненте доступен только для этого компонента и всех его детей.

Здесь служба APP_CONFIG должна быть доступна по всей приложение, поэтому оно зарегистрировано в поставщиках AppModule @NgModule массив. Но поскольку HeroService используется только в Heroes и нигде больше, имеет смысл зарегистрировать его в HeroesComponent.

Также см. "Должен ли я добавлять поставщиков приложений в корневой AppModule или root AppComponent?" в FAQ NgModule.

Итак, в вашем случае просто измените инъекции на поставщиков, как показано ниже:

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

Также в новых версиях Angular, @View и некоторых других материалах пропало.

Для получения дополнительной информации посетите здесь.

1

Angular2 требует, чтобы вы объявили все инъекции в вызове функции загрузки. Без этого ваша служба не является инъекционным объектом.

bootstrap(MyAppComponent,[NameService]);
  • 1
    Это не совсем правильно. Мы можем включить сервис в bootstrap () или в массив providers в объекте конфигурации компонента. Если он включен в массив providers , мы получаем один экземпляр для каждого связанного компонента. См. Документ «Иерархические инжекторы» для получения дополнительной информации.
  • 0
    да, как сказал @MarkRajcok, во время начальной загрузки мы также предоставляем только те услуги, которые мы должны использовать во всем приложении. при этом нам не нужно вводить каждый раз в провайдере, потому что он создаст экземпляр для каждого компонента.
0

добавьте свою службу в каталог поставщиков [] в файле app.module.ts. Как ниже

//здесь моя служба CarService

app.module.ts

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

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

Добавьте @Injectable к вашей службе как:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

и в вашем компоненте добавить поставщиков как:

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

или если вы хотите получить доступ к своей службе по всему приложению, которое вы можете передать в приложении-провайдере

Ещё вопросы

Сообщество Overcoder
Наверх
Меню