简体   繁体   English

Angular2异常:没有服务提供者

[英]Angular2 Exception: No provider for Service

I'm unable to instantiate my application when I have the component which is nested under the root component providing a component which it uses in it's constructor. 当我拥有嵌套在根组件下的组件时,我无法实例化我的应用程序,该组件providing了在其构造函数中使用的组件。

import {Component, Injectable} from 'angular2/core';


@Component()
export class GrandChild(){
  constructor () {
    this.hello = "hey!"
  }
}

@Component({
  providers: [GrandChild]
})
@Injectable()
export class Child {
    constructor(public grandchild: GrandChild) {
        this.grandchild = grandchild;
    }
}

@Component({
    providers: [Child],
    template: `Everything rendered fine!`,
    selector: 'app'
})

export class App {
    kid: Child;

    constructor(public child: Child) {
        this.kid = child;
    }
}

EXCEPTION: No provider for GrandChild! (App -> Child -> GrandChild)

I'm wondering why this behavior is illegal. 我想知道为什么这种行为是非法的。 Let's say I wanted to use the GrandChild class in my Child class and simply reference the Child class in my App class. 假设我想在Child类中使用GrandChild类,而在App类中仅引用Child类。 This seems to be impossible. 这似乎是不可能的。

What is the correct way to create the provide hierarchy? 创建provide层次结构的正确方法是什么?

Thanks a bunch. 谢谢你

PLNKR: http://plnkr.co/edit/5Z0QMAEyZNUAotZ6r7Yi?p=preview PLNKR: http ://plnkr.co/edit/5Z0QMAEyZNUAotZ6r7Yi?p=preview

You can inject directly the parent component into a component without specifying it into component providers. 您可以直接将父组件注入到组件中,而无需将其指定到组件提供程序中。 To do that you need to use component into other ones and set it into the directives attribute: 为此,您需要在其他组件中使用组件并将其设置为directives属性:

@Component({
  selector: 'child',
  template: `
    <div></div>
  `
})
export class Child {
  constructor(@Inject(forwardRef(() => App)) parent: App) {
  }
}

@Component({
  directives: [Child],
  template: `
    Everything rendered fine!
    <child></child>
  `,
  selector: 'app'
})
export class App {
  constructor() {
  }
}

What is a bit strange in your sample is that you didn't define selector and template properties for components Child and GrandChild . 您的示例中有些奇怪的是,您没有为组件ChildGrandChild定义selectortemplate属性。 Are they really components? 它们真的是组成部分吗?

In your sample, you made things in the wrong way. 在您的示例中,您以错误的方式进行操作。 If you want to get instances of child component from a parent component, you need to leverage the @ViewChild decorator to reference the child component from the parent one by injection: 如果要从父组件获取子组件的实例,则需要利用@ViewChild装饰器通过注入从父组件引用子组件:

import { Component, ViewChild } from 'angular2/core';  

(...)

@Component({
  selector: 'my-app',
  template: `
    <h1>My First Angular 2 App</h1>
    <child></child>
    <button (click)="submit()">Submit</button>
  `,
  directives:[App]
})
export class AppComponent { 
  @ViewChild(SearchBar) searchBar:SearchBar;

  (...)

  someOtherMethod() {
    this.searchBar.someMethod();
  }
}

Here is the updated plunkr: http://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview . 这是更新的plunkr: http ://plnkr.co/edit/mrVK2j3hJQ04n8vlXLXt?p=preview。

You can notice that the @Query parameter decorator could also be used: 您会注意到,也可以使用@Query参数修饰符:

export class AppComponent { 
  constructor(@Query(SearchBar) children:QueryList<SearchBar>) {
    this.childcmp = children.first();
  }

  (...)
}

You can notice that you don't need the @Injectable decorator when you have the @Component one... 您可能会注意到,拥有@Component一个时就不需要@Injectable装饰器了。

You can fix it by adding GrandChild to App 's providers. 您可以通过将GrandChild添加到App的提供App来修复它。

However, I don't understand why you were annotating Child and GrandChild as @Component when you're using them as services. 但是,我不明白为什么在将它们用作服务时为什么将ChildGrandChild标注为@Component I guess this is what you actually wanted to do. 我想这就是您真正想要做的。

@Injectable()
export class GrandChild(){
  constructor () {
    this.hello = "hey!"
  }
}

@Injectable()
export class Child {
    tire: string;
    constructor(public grandchild: GrandChild) {
        this.grandchild = grandchild;
    }
}

@Component({
    providers: [Child, GrandChild],
    template: `Everything rendered fine!`,
    selector: 'app'
})
export class App {
    thread: Thread;
    selected: boolean = false;
    kid: Child;

    constructor(public child: Child) {
        this.kid = child;
    }
}

See updated plnkr demo . 请参阅更新的plnkr演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM