2016-02-26 68 views
2

我一直在寻找一个解决方案。我已经试过了一堆从@input,@Query,dynamicContentLoader,@注入,@Inject(forwardRef(()不同的事情,但一直没能还没有想出解决办法Angular 2,如何将选项从父组件传递给子组件?

我的例子结构:

parent.ts

import {Component} from 'angular2/core'; 

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

export class Parent 
{ 
    private options:any; 

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

child.ts

import {Component} from 'angular2/core'; 

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

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 component at this point 
     // but I am not sure how to do this with Angular 2 
     console.log(options) <- this should come from the parent 

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

这是DOM我目前的HTML输出,所以这部分工作正常

<parent-component> 
    <child-component></child-component> 
</parent-component> 

问题概括为:

如何传递从父组件选项的子组件和有那些在子构造函数中可用的选项?

+1

简单绑定有什么问题?子中的@Input()'和

+0

我已经看到过很多次。它很可能是解决方案。无论出于什么原因,我都不知道问题是如何结合在一起的。我在@Input中混淆了一段时间..但是我认为我很难将所有隐含的东西包裹起来,以及如何使它正常工作。 –

+0

基本上我已经尝试了所有这些..'@Input,@Query,dynamicContentLoader,@Inject,@Inject(forwardRef(()'但我一直无法让他们做我想做的事情。我不是说他们做不到,但或多或​​少,我最大限度地减少了我的问题,以表明我试图达到什么样的最终结果。其中之一可能是解决方案。 –

回答

5

父母对孩子是最简单的形式,但它在构造函数中不可用,仅在ngOnInit()(或更高版本)中可用。

这只需要子组件中的@Input() someField;,并使用绑定,这可以从父项传递给子项。在父更新的孩子(而不是其他方向)

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

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

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

有它可用在构造函数中使用共享服务进行更新。共享服务被注入到这两个组件的构造函数中。为了注入工作,服务需要在父组件或以上但不在儿童中注册。这种方式都获得相同的实例。 在父项中设置一个值并在客户端中读取它。

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

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

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

更新

没有太大的区别。对于DI,只能使用构造函数。如果你想注入某些东西,它必须通过构造函数。当发生额外的初始化时(如正在处理的绑定),Angular将调用ngOnInit()。例如,如果您拨打网络电话,则在ngOnInit的构造函数中执行此操作并不重要,因为调用服务器的时间安排在稍后(异步)。当前同步任务完成后,JavaScript查找下一个计划任务并处理它(等等)。因此,无论您将它放在哪里,在构造函数中启动的服务器调用实际上都可以在ngOnInit()之后发送。

+0

我很抱歉拖出来。你能否详细说明ngOnInit()与构造函数()之间的区别(或者知道任何好的资源),我是否还需要构造函数来处理所有组件? –

+0

评论太长,我更新了答案。 –

+0

谢谢,解释和解答。这清除了我很多的困惑。这也解释了为什么'@Input()'在构造函数中不起作用。 –

1

你可以使用一个@Input参数:

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

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

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

注意的options值是在ngOnInit可用的,而不是在构造函数中。看一看组件的生命周期挂钩的详细信息:

,并提供选项,如下描述下:

import {Component} from 'angular2/core'; 

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

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

如果要实现自定义的事件:孩子触发器一个事件和父注册将被通知。使用@Output

+0

感谢您的回复,我实际上已经在发布之前尝试过。只是再次尝试验证。 'this.options'回到未定义状态。 –

+1

对不起,我看着这个倒退。我看到你贴的基本上和@Gunter有相同的答案。不过,我不得不接受一个。所以我和他一起去了,因为他对'constructor()'和'ngOnInit()'的很好的解释,并且如果需要的话,还有一个用于访问'constructor()'中的信息的替代解决方案。尽管谢谢你的回应! –

相关问题