Angular ไม่มีผู้ให้บริการสำหรับ NameService


326

ฉันมีปัญหาในการโหลดคลาสลงในคอมโพเนนต์ 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;
    }
}

ฉันได้รับข้อความแสดงข้อผิดพลาดNo provider for NameServiceอยู่เรื่อย ๆ

มีคนช่วยฉันตรวจสอบปัญหาด้วยรหัสของฉันได้ไหม


6
ตั้งแต่ Alpha 42: @Component ({ผู้ให้บริการ: [NameService]})
timmz

คำตอบ:


470

คุณต้องใช้providersแทนinjectables

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

โค้ดตัวอย่างสมบูรณ์ที่นี่


7
@unobf งบการนำเข้าดูไม่แตกให้ฉัน คำตอบก่อนหน้านี้อาจถูกต้องสำหรับอัลฟาที่เก่ากว่าของไลบรารี angular2 คำแนะนำดั้งเดิมหมายถึงอัลฟ่า -28 ฉันใช้อัลฟ่า 35 นอกจากนี้ฉันยังให้ลิงก์ไปยังตัวอย่างโค้ดที่สมบูรณ์ดังนั้นฉันคิดว่าฉันได้ให้ข้อมูลค่อนข้างมาก
Klas Mellbourn

4
การอัปเดตสำหรับผู้ใช้ Google ในอนาคต: การใช้providersงานกับเบต้าล่าสุด (เบต้า 0)
nathanhleung

@nathanhleung ทั้งการเชื่อมโยงและผู้ให้บริการทำงาน - เป็นแบบชั่วคราวหรือว่าพวกเขาเพิ่งทำแบบเดียวกันภายใน
Simon_Weaver

@Simon_Weaver อืมพวกเขาอาจมีการเปลี่ยนแปลงในรุ่นเบต้าล่าสุด - ในรุ่นเบต้าฉันไม่สามารถทำงานกับมันได้bindings
nathanhleung

1
จะเป็นอย่างไรถ้ามีการใช้บริการจากบริการอื่น ฉันเพิ่มไปยังผู้ให้บริการโมดูลซึ่งฉันคิดว่าจะให้บริการทั่วโลก แต่ยังได้รับข้อผิดพลาดนั้น
Sonic Soul

79

ใน Angular 2 มีสามที่ที่คุณสามารถ "ให้บริการ" ได้:

  1. บูต
  2. องค์ประกอบราก
  3. ส่วนประกอบหรือคำสั่งอื่น ๆ

"ตัวเลือกผู้ให้บริการ bootstrap นั้นมีจุดประสงค์เพื่อกำหนดค่าและลบล้างบริการที่ลงทะเบียนล่วงหน้าของ Angular เช่นการสนับสนุนการกำหนดเส้นทาง" - การอ้างอิง

หากคุณต้องการ NameService หนึ่งอินสแตนซ์ในแอปทั้งหมดของคุณ (เช่น Singleton) ให้รวมไว้ในprovidersอาร์เรย์ขององค์ประกอบรูทของคุณ:

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

Plunker

หากคุณต้องการมีหนึ่งอินสแตนซ์ต่อองค์ประกอบให้ใช้providersอาร์เรย์ในวัตถุการกำหนดค่าของส่วนประกอบแทน:

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

ดูเอกสารหัวฉีดลำดับชั้นเพื่อดูข้อมูลเพิ่มเติม


4
นี่เป็นคำตอบที่ดีจริงๆ นอกจากนี้ยังอธิบายถึงความแตกต่างระหว่างการประกาศบริการในส่วนประกอบรากเปรียบเทียบกับการประกาศในองค์ประกอบย่อยอื่น ๆ
Taf

34

ตั้งแต่ Beta Angular 2:

เพิ่ม@Injectableการบริการของคุณเป็น:

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

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

    getNames() {
        return this.names;
    }
}

และองค์ประกอบ config ของคุณเพิ่มprovidersเป็น:

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

22

คุณควรจะฉีดNameServiceภายในprovidersอาร์เรย์ของคุณAppModule's 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 ที่ยอมรับแสดงขึ้นมา


ฉันได้ลองเพิ่มบริการใน app.module.shared.ts ในส่วน @NgModule: ผู้ให้บริการ: [DataManagerService] แต่ยังได้รับข้อผิดพลาด: ข้อผิดพลาด: ไม่มีผู้ให้บริการสำหรับ DataManagerService!
พอล

1
@ พอลคุณฉีดบริการของคุณในโมดูลที่ถูกต้อง? และDataManagerServiceมี@Injectableมัณฑนากรมากกว่ามัน?
Pankaj Parkar

15

น่าประหลาดที่ไวยากรณ์มีการเปลี่ยนแปลงอีกครั้งใน Angular รุ่นล่าสุด :-) จากเอกสาร Angular 6 :

เริ่มต้นด้วย Angular 6.0 วิธีที่ต้องการในการสร้างบริการซิงเกิลตันคือการระบุบริการที่ควรให้ในรูทแอปพลิเคชัน สิ่งนี้ทำได้โดยการตั้งค่าที่ระบุไว้ในรูทบนมัณฑนากร @Injectable ของบริการ:

src / app / user.service.0.ts

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

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

14

คุณควรฉีด NameService ในอาร์เรย์ผู้ให้บริการข้อมูลเมตาของ NgModule ของ AppModule

@NgModule({
   providers: [MyService]
})

และให้แน่ใจว่าอิมพอร์ตในคอมโพเนนต์ของคุณด้วยชื่อเดียวกัน (case sensitive), เนื่องจาก SystemJs เป็นแบบ case-sensitive (โดยการออกแบบ) หากคุณใช้ชื่อพา ธ ที่แตกต่างกันในไฟล์โครงการของคุณเช่นนี้:

main.module.ts

import { MyService } from './MyService';

ของคุณ component.ts

import { MyService } from './Myservice';

จากนั้น System js จะทำการอิมพอร์ตสองครั้ง


1
ยอดเยี่ยม เมื่อใช้บาร์เรลเพื่อนำเข้ากลุ่มฉันพบข้อผิดพลาดนี้ เคล็ดลับ SystemJS ของคุณช่วยให้ฉัน :)
Jony adamit


7

Angular 2 มีการเปลี่ยนแปลงนี่คือสิ่งที่รหัสด้านบนของคุณควรมีลักษณะ:

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

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

นอกจากนี้คุณอาจต้องการใช้ getters และ setters ในบริการของคุณ:

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) ใหม่และเริ่มต้นทำงานที่นั่นก่อน มันจะตั้งค่าทุกอย่างให้คุณ เมื่อมันทำงานอยู่ที่นั่นให้คัดลอกมันไปยังสภาพแวดล้อมอื่นของคุณและทำการทดลองปัญหาใด ๆ กับสภาพแวดล้อมนั้น


6

ข้อผิดพลาดNo provider for NameServiceเป็นปัญหาทั่วไปที่ผู้เริ่มต้น Angular2 เผชิญ

เหตุผล : ก่อนที่จะใช้บริการที่กำหนดเองคุณต้องลงทะเบียนกับ NgModule ก่อนโดยเพิ่มลงในรายการผู้ให้บริการ:

สารละลาย:

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


4

สวัสดีคุณสามารถใช้สิ่งนี้ในไฟล์. ts ของคุณ:

ก่อนนำเข้าบริการของคุณในไฟล์. tts นี้:

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> `   
    })


3

ในแองกูลาร์คุณสามารถลงทะเบียนบริการได้สองวิธี:

1. ลงทะเบียนบริการในโมดูลหรือส่วนประกอบรูต

ผลกระทบ:

  • มีอยู่ในส่วนประกอบทั้งหมด
  • พร้อมใช้งานบนแอปพลิเคชันตลอดชีวิต

คุณควรระมัดระวังถ้าคุณลงทะเบียนบริการในโมดูลที่โหลดแบบสันหลังยาว:

  • บริการนี้มีเฉพาะในส่วนประกอบที่ประกาศในโมดูลนั้นเท่านั้น

  • บริการนี้จะพร้อมใช้งานในแอปพลิเคชันอายุการใช้งานเฉพาะเมื่อโหลดโมดูลเท่านั้น

2. ลงทะเบียนบริการในแอปพลิเคชันอื่น ๆ

ผลกระทบ:

  • จะถูกฉีดอินสแตนซ์ที่แยกต่างหากของบริการลงในคอมโพเนนต์

คุณควรระมัดระวังหากคุณลงทะเบียนบริการลงในส่วนประกอบแอปพลิเคชันอื่น ๆ

  • อินสแตนซ์ของบริการการฉีดจะมีให้เฉพาะในองค์ประกอบและลูก ๆ ทั้งหมดของมัน

  • อินสแตนซ์จะพร้อมใช้งานในช่วงอายุส่วนประกอบ


2

คุณต้องเพิ่มลงในอาร์เรย์ผู้ให้บริการซึ่งรวมถึงการพึ่งพาส่วนประกอบของคุณทั้งหมด

ดูหัวข้อนี้ในเอกสารประกอบเชิงมุม:

การลงทะเบียนผู้ให้บริการในองค์ประกอบ

นี่คือ 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 หรือรูท AppComponent หรือไม่" ใน NgModule คำถามที่พบบ่อย

ดังนั้นในกรณีของคุณเพียงเปลี่ยน injectables เป็นผู้ให้บริการด้านล่าง:

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

นอกจากนี้ใน Angular เวอร์ชันใหม่ @View และของอื่น ๆ ก็หายไป

สำหรับข้อมูลเพิ่มเติมโปรดเยี่ยมชมที่นี่


2

เพิ่มบริการของคุณไปยังผู้ให้บริการ [] อาร์เรย์ในไฟล์ app.module.ts ชอบด้านล่าง

// ที่นี่บริการของฉันคือ CarService

app.module.ts

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

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

1

Angular2 ต้องการให้คุณประกาศ injectables ทั้งหมดในการเรียกใช้ฟังก์ชัน bootstrap บริการของคุณจะไม่เป็นวัตถุที่สามารถทำการฉีดได้

bootstrap(MyAppComponent,[NameService]);

1
มันไม่ถูกต้องนัก เราสามารถรวมบริการใน bootstrap () หรือในprovidersอาร์เรย์ในวัตถุการกำหนดค่าของส่วนประกอบ ถ้ามันรวมอยู่ในprovidersอาร์เรย์เราจะได้รับหนึ่งอินสแตนซ์ต่อองค์ประกอบที่ถูกผูกไว้ ดูเอกสารหัวฉีดลำดับชั้นเพื่อดูข้อมูลเพิ่มเติม
Mark Rajcok

ใช่ดังที่ได้กล่าวโดย @MarkRajcok นอกจากนี้เรายังให้บริการเฉพาะในช่วงเวลาที่ bootstrap ที่เราต้องใช้ตลอดทั้งแอพ โดยการทำเช่นนั้นเราไม่จำเป็นต้องฉีดทุกครั้งในผู้ให้บริการเพราะมันจะสร้างอินสแตนซ์สำหรับทุกองค์ประกอบ
Pardeep Jain

1

เพิ่ม @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]
})

หรือถ้าคุณต้องการเข้าถึงบริการของคุณทั่วทั้งแอปพลิเคชันคุณสามารถส่งผ่านผู้ให้บริการแอป


1

blockquote

การลงทะเบียนผู้ให้บริการในองค์ประกอบ

นี่คือ HeroesComponent ที่ได้รับการแก้ไขซึ่งลงทะเบียน HeroService ในอาร์เรย์ผู้ให้บริการ

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

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

@Component({
  selector: 'my-heroes',
  providers: [HeroService],
  template: `
  `
})
export class HeroesComponent { }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.