最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2, How to pass options from parent component to child component? - Stack Overflow

programmeradmin1浏览0评论

I have been looking for a solution for this for a while. I have tried a bunch of different things from @Input, @Query, dynamicContentLoader, @Inject, @Inject(forwardRef(() but haven't been able to figure this out yet.

My Example Structure:

parent.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'my-app',
    directives : [Child],
    template   : `<parent-ponent></parent-ponent>`
})

export class Parent
{
    private options:any;

    constructor()
    {
        this.options = {parentThing:true};
    }
}

child.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'parent-ponent',
    template   : `<child-ponent></child-ponent>`
})

export class Child
{
    constructor(private options:any) <- maybe I can pass them in here somehow?
    {
        // what I am trying to do is get options from
        // the parent ponent at this point
        // but I am not sure how to do this with Angular 2
        console.log(options) <- this should e from the parent

        // how can I get parent options here?
        // {parentThing:true}
    }
}

This is my current HTML output in the DOM, so this part is working as expected

<parent-ponent>
   <child-ponent></child-ponent>
</parent-ponent>

Question Summarized:

How can I pass options from a parent ponent to a child ponent and have those options available in the child constructor?

I have been looking for a solution for this for a while. I have tried a bunch of different things from @Input, @Query, dynamicContentLoader, @Inject, @Inject(forwardRef(() but haven't been able to figure this out yet.

My Example Structure:

parent.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'my-app',
    directives : [Child],
    template   : `<parent-ponent></parent-ponent>`
})

export class Parent
{
    private options:any;

    constructor()
    {
        this.options = {parentThing:true};
    }
}

child.ts

import {Component} from 'angular2/core';

@Component({
    selector   : 'parent-ponent',
    template   : `<child-ponent></child-ponent>`
})

export class Child
{
    constructor(private options:any) <- maybe I can pass them in here somehow?
    {
        // what I am trying to do is get options from
        // the parent ponent at this point
        // but I am not sure how to do this with Angular 2
        console.log(options) <- this should e from the parent

        // how can I get parent options here?
        // {parentThing:true}
    }
}

This is my current HTML output in the DOM, so this part is working as expected

<parent-ponent>
   <child-ponent></child-ponent>
</parent-ponent>

Question Summarized:

How can I pass options from a parent ponent to a child ponent and have those options available in the child constructor?

Share Improve this question edited Mar 3, 2016 at 16:12 khollenbeck asked Feb 26, 2016 at 19:09 khollenbeckkhollenbeck 16.2k18 gold badges68 silver badges102 bronze badges 7
  • 1 What's the problem with simple binding? @Input() in the child and <child [someInput]="someOption"? – Günter Zöchbauer Commented Feb 26, 2016 at 19:17
  • I have seen that mentioned many times. It very well could be the solution. The problem is for whatever reason I haven't understood how everything should hook together. I messed around with @Input for sometime.. But I think I am having a hard time wrapping my head around all of the implicit stuff that happens and how to get it to work properly. – khollenbeck Commented Feb 26, 2016 at 19:23
  • Basically I have tried all of these.. @Input, @Query, dynamicContentLoader, @Inject, @Inject(forwardRef(() But I haven't been able to get them to do what I am trying to do. So I am not saying they can't. But more or less I minimized my question to show what type of end result I am trying to achieve. One of those could be the solution. – khollenbeck Commented Feb 26, 2016 at 19:25
  • Just saw, why do you need them available in the constructor? – Günter Zöchbauer Commented Feb 26, 2016 at 19:31
  • See my updated answer, but why do you need it in the constructor? – Günter Zöchbauer Commented Feb 26, 2016 at 19:34
 |  Show 2 more ments

2 Answers 2

Reset to default 7

Parent to child is the simplest form of all but it's not available in the constructor, only in ngOnInit() (or later).

This only requires an @Input() someField; in the child ponent and using binding this can be passed from parent to children. Updates in the parent are updated in the child (not the other direction)

@Component({
  selector: 'child-ponent',
  template'<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  @Input() someValueFromParent:string;

  ngOnInit() {
    console.log(this.someValue);
  }
}

@Component({
  selector: 'parent-ponent',
  template: '<child-ponent [someValueFromParent]="someValue"></child-ponent>'
})
class ParentComponent {
  someValue:string = 'abc';
}

to have it available in the constructor use a shared service. A shared service is injected into the constructor of both ponents. For injection to work the service needs to be registered in the parent ponent or above but not in the child. This way both get the same instance. Set a value in the parent and read it in the client.

@Injectable()
class SharedService {
  someValue:string;
}

@Component({
  selector: 'child-ponent',
  template: '<div>someValueFromParent: {{someValueFromParent}}</div>'
})  
class ChildComponent {
  constructor(private sharedService:SharedService) {
    this.someValue = sharedService.someValue;
  }
  someValue:string = 'abc';
}

@Component({
  selector: 'parent-ponent',
  providers: [SharedService],
  template: '<child-ponent></child-ponent>'
})
class ParentComponent {
  constructor(private sharedService:SharedService) {
    sharedService.someValue = this.someValue;
  }
  someValue:string = 'abc';
}

update

There is not much difference. For DI only the constructor can be used. If you want something injected it has to be through the constructor. ngOnInit() is called by Angular when additional initialization has taken place (like bindings being processed). For example if you make a network call it doesn't matter if you do it in the constructor on in ngOnInit because the call to the server is scheduled for later anyway (async). When the current sync task is pleted, JavaScript looks for the next scheduled task and processes it (and so on). Therefore it's probably so that the server call initiated in the constructor is actually sent after ngOnInit() anyway no matter where you place it.

You could use an @Input parameter:

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

@Component({
  selector   : 'parent-ponent',
  template   : `<child-ponent></child-ponent>`
})
export class Child {
  @Input()
  options:any;

  ngOnInit() {
    console.log(this.options);
  }
}

Notice that the value of options is available in the ngOnInit and not in the constructor. Have a look at the ponent lifecycle hooks for more details:

  • https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

And provides the options as decribed below:

import {Component} from 'angular2/core';

@Component({
  selector   : 'my-app',
  directives : [Child],
  template   : `<parent-ponent [options]="options"></parent-ponent>`
})
export class Parent {
  private options:any;

  constructor() {
    this.options = {parentThing:true};
  }
}

If you want to implement custom events: child triggers an event and the parent register to be notified. Use @Output.

发布评论

评论列表(0)

  1. 暂无评论