Tidak ada penyedia untuk NameService


326

Saya punya masalah memuat kelas ke komponen Angular. Saya sudah mencoba menyelesaikannya untuk waktu yang lama; Saya bahkan sudah mencoba menggabungkan semuanya dalam satu file. Apa yang saya miliki adalah:

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

layanan / NameService.ts

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

Saya terus menerima pesan kesalahan yang mengatakan No provider for NameService.

Dapatkah seseorang membantu saya menemukan masalah dengan kode saya?


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

Jawaban:


470

Anda harus menggunakan providerssebagai gantinyainjectables

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

Lengkapi contoh kode di sini .


7
@ unobf pernyataan impor tidak terlihat rusak bagi saya. Jawaban sebelumnya mungkin benar untuk alfa lama dari perpustakaan angular2. Panduan asli mengacu pada alpha-28, saya menggunakan alpha 35. Juga, saya memberikan tautan ke contoh kode lengkap, jadi saya pikir saya telah memberikan informasi yang cukup banyak.
Klas Mellbourn

4
Pembaruan untuk googler masa depan: menggunakan providerskarya pada beta terbaru (beta 0).
nathanhleung

@nathanhleung bindings dan provider bekerja - apakah ini sementara atau apakah mereka hanya melakukan hal yang sama secara internal
Simon_Weaver

@Simon_Weaver hmm mereka mungkin telah mengubahnya dalam beta terbaru - dalam beta.0 Saya tidak bisa membuatnya bekerja denganbindings
nathanhleung

1
bagaimana jika layanan tersebut digunakan dari layanan lain? saya menambahkannya ke penyedia modul yang saya pikir akan membuatnya tersedia secara global, tetapi masih mendapatkan kesalahan itu
Sonic Soul

79

Di Angular 2 ada tiga tempat Anda dapat "menyediakan" layanan:

  1. bootstrap
  2. komponen root
  3. komponen atau arahan lain

"Opsi penyedia bootstrap dimaksudkan untuk mengonfigurasi dan menimpa layanan pra-registrasi Angular sendiri, seperti dukungan peruteannya." - referensi

Jika Anda hanya ingin satu instance NameService di seluruh aplikasi Anda (yaitu, Singleton), maka sertakan dalam providersarray komponen root Anda:

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

Plunker

Jika Anda lebih suka memiliki satu instance per komponen, gunakan providersarray di objek konfigurasi komponen sebagai gantinya:

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

Lihat dokumen Hierarchical Injectors untuk informasi lebih lanjut.


4
Ini jawaban yang sangat bagus. Lebih lanjut dijelaskan perbedaan antara mendeklarasikan layanan dalam komponen root versus mendeklarasikan dalam komponen anak lainnya.
Taf

34

Pada Angular 2 Beta:

Tambahkan @Injectableke layanan Anda sebagai:

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

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

    getNames() {
        return this.names;
    }
}

dan ke konfigurasi komponen Anda tambahkan providerssebagai:

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

22

Anda harus menyuntikkan NameServicedalam providersarray Anda AppModule's NgModulemetadata.

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

}

Jika Anda ingin membuat Ketergantungan untuk tingkat komponen tertentu tanpa peduli tentang keadaan aplikasi Anda, maka Anda dapat menyuntikkan ketergantungan itu pada providersopsi metadata komponen seperti jawaban @Klass diterima yang diperlihatkan.


Saya telah mencoba menambahkan layanan di app.module.shared.ts di bagian @NgModule: penyedia: [DataManagerService] tetapi masih mendapatkan kesalahan: Kesalahan: Tidak ada penyedia untuk DataManagerService!
Paul

1
@ Paul apakah Anda menyuntikkan layanan Anda di Modul yang benar? dan apakah DataManagerServiceada @Injectabledekorator di atasnya?
Pankaj Parkar

15

Secara mengejutkan, sintaks telah berubah lagi dalam versi terbaru Angular :-) Dari Angular 6 docs :

Dimulai dengan Angular 6.0, cara yang lebih disukai untuk membuat layanan singleton adalah menentukan layanan yang harus disediakan di root aplikasi. Ini dilakukan dengan menyetel yang disediakan ke root pada dekorator @Injectable layanan:

src / app / user.service.0.ts

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

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

14

Anda harus menyuntikkan NameService di dalam array penyedia metadata NgModule AppModule Anda.

@NgModule({
   providers: [MyService]
})

dan pastikan impor di komponen Anda dengan nama yang sama (case sensitive), karena SystemJs case sensitive (sesuai desain). Jika Anda menggunakan nama jalur berbeda di file proyek Anda seperti ini:

main.module.ts

import { MyService } from './MyService';

your-component.ts

import { MyService } from './Myservice';

maka Sistem js akan membuat impor ganda


1
Luar biasa! Saat menggunakan barel untuk mengelompokkan impor saya menemukan kesalahan ini. Tip SystemJS Anda membantu saya :)
Jony Adamit

12

Di Angular v2 dan lebih tinggi sekarang:

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


7

Angular 2 telah berubah, berikut tampilan bagian atas kode Anda:

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

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

Selain itu, Anda mungkin ingin menggunakan getter dan setter dalam layanan Anda:

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

Kemudian di aplikasi Anda, Anda cukup melakukan:

this.names = nameService.names;

Saya sarankan Anda pergi ke plnkr.co dan membuat plunk Angular 2 (ES6) baru dan membuatnya bekerja di sana terlebih dahulu. Ini akan mengatur segalanya untuk Anda. Setelah berhasil di sana, salin ke lingkungan Anda yang lain dan atasi masalah apa pun dengan lingkungan itu.


6

Kesalahan No provider for NameServiceadalah masalah umum yang dihadapi banyak pemula Angular2.

Alasan : Sebelum menggunakan layanan khusus, Anda harus mendaftarkannya terlebih dahulu ke NgModule dengan menambahkannya ke daftar penyedia:

Larutan:

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


4

Hai, Anda dapat menggunakan ini dalam file .ts Anda:

pertama-tama impor layanan Anda dalam file .ts ini:

import { Your_Service_Name } from './path_To_Your_Service_Name';

Kemudian dalam file yang sama Anda dapat menambahkan providers: [Your_Service_Name]:

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


3

Di Angular Anda dapat mendaftarkan layanan dengan dua cara:

1. Daftarkan layanan dalam modul atau komponen root

Efek:

  • Tersedia untuk semua komponen
  • Tersedia untuk aplikasi seumur hidup

Anda harus berhati-hati jika mendaftarkan layanan ke modul malas yang dimuat:

  • Layanan hanya tersedia ke komponen yang dinyatakan dalam modul itu

  • Layanan akan tersedia pada aplikasi seumur hidup hanya ketika modul dimuat

2. Daftarkan layanan ke komponen aplikasi lainnya

Efek:

  • Akan disuntikkan instance Layanan yang terpisah ke dalam komponen

Anda harus berhati-hati jika mendaftarkan layanan ke komponen aplikasi lainnya

  • Mesin virtual dari layanan yang disuntikkan akan tersedia hanya ke dalam komponen dan semua anak-anaknya.

  • Mesin virtual akan tersedia pada masa pakai komponen.


2

Anda perlu menambahkannya ke array penyedia, yang mencakup semua keadaan pada komponen Anda.

Lihatlah bagian ini dalam dokumentasi sudut:

Mendaftarkan penyedia dalam suatu komponen

Berikut adalah HeroesComponent yang direvisi yang mendaftarkan HeroService dalam larik penyedianya.

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

Kapan menggunakan NgModule versus komponen aplikasi

Di satu sisi, penyedia di NgModule terdaftar di root injector. Itu berarti bahwa setiap penyedia yang terdaftar dalam NgModule akan dapat diakses di seluruh aplikasi.

Di sisi lain, penyedia terdaftar dalam komponen aplikasi hanya tersedia pada komponen itu dan semua anak-anaknya.

Di sini, layanan APP_CONFIG perlu tersedia di seluruh aplikasi, jadi itu terdaftar di array penyedia AppModule @NgModule. Tetapi karena HeroService hanya digunakan di dalam area fitur Heroes dan tidak di tempat lain, masuk akal untuk mendaftarkannya di HeroesComponent.

Juga lihat "Haruskah saya menambahkan penyedia seluruh aplikasi ke root AppModule atau root AppComponent?" di FAQ NgModule.

Jadi dalam kasus Anda, cukup ganti suntikan ke penyedia seperti di bawah ini:

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

Juga di versi baru Angular, @View dan beberapa barang lainnya hilang.

Untuk info lebih lanjut, kunjungi di sini .


2

tambahkan layanan Anda ke array penyedia [] dalam file app.module.ts. Seperti di bawah ini

// di sini layanan saya adalah CarService

app.module.ts

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

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

1

Angular2 mengharuskan Anda untuk mendeklarasikan semua injeksi dalam panggilan fungsi bootstrap. Tanpa ini layanan Anda bukanlah objek yang dapat disuntikkan.

bootstrap(MyAppComponent,[NameService]);

1
Ini tidak sepenuhnya benar. Kami dapat menyertakan layanan di bootstrap (), atau dalam providersarray di objek konfigurasi komponen. Jika dimasukkan dalam providersarray, kami mendapatkan satu instance per komponen terikat. Lihat dokumen Hierarchical Injectors untuk informasi lebih lanjut.
Mark Rajcok

ya seperti yang dikatakan oleh @MarkRajcok juga kami hanya menyediakan layanan tersebut pada saat bootstrap mana yang harus kita gunakan di seluruh aplikasi. dengan melakukan itu kami tidak perlu menyuntikkan setiap kali di penyedia karena akan membuat contoh untuk setiap komponen
Pardeep Jain

1

Tambahkan @Injectable ke layanan Anda sebagai:

export class NameService {
    names: Array<string>;

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

    getNames() {
        return this.names;
    }
}

dan di komponen Anda tambahkan penyedia sebagai:

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

atau jika Anda ingin mengakses layanan Anda di seluruh aplikasi, Anda dapat mengirimkan penyedia aplikasi


1

Blokir

Mendaftarkan penyedia dalam suatu komponen

Berikut adalah HeroesComponent yang direvisi yang mendaftarkan HeroService dalam larik penyedianya.

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.