Typescript 角度2子组件检测父组件中的更改

Typescript 角度2子组件检测父组件中的更改,typescript,angular,Typescript,Angular,我有一个组件,它显示“项”列表,这些项是使用选择器创建的组件。当单击以更新所有子组件的“状态”时,我有一个我想要的复选框 我真的很难找到正确的解决方法。 有关更多信息,请参阅 //我们的根应用程序组件 从'angular2/core'导入{Component,EventEmitter} 类项目{ 名称:布尔; 构造函数(名称:string){ this.name=名称; } } @组成部分({ 选择器:“我的项目”, 模板:` {{state}} ` }) 导出类MyItemComponent{

我有一个组件,它显示“项”列表,这些项是使用选择器创建的组件。当单击以更新所有子组件的“状态”时,我有一个我想要的复选框

我真的很难找到正确的解决方法。 有关更多信息,请参阅

//我们的根应用程序组件
从'angular2/core'导入{Component,EventEmitter}
类项目{
名称:布尔;
构造函数(名称:string){
this.name=名称;
}
}
@组成部分({
选择器:“我的项目”,
模板:`
{{state}}
`
})
导出类MyItemComponent{
状态:boolean=false;
}
@组成部分({
选择器:“我的应用程序”,
模板:`
{{state}}
`,
指令:[MyItemComponent]
})
导出类应用程序{
状态:boolean=true;
项目:项目[]=[];
构造函数(){
this.items.push(新项(“hello”);
此.items.push(新项(“测试”));
}
}

更新

@组件({
选择器:“我的项目”,
输入:[“状态”];//已添加
模板:`
{{state}}
`
})
导出类MyItemComponent{
状态:boolean=false;
}
然后像这样使用它


原创

角度变化检测不会检测阵列中的变化。
这将使它发挥作用:

constructor(){
this.items.push(新项(“hello”);
此.items.push(新项(“测试”));
this.items=this.items.slice();
}
这样,一个新数组(副本)被分配给
This.items
,因此Angular会将其识别为更改

MyItem
中,您需要
输入

@组件({
选择器:“我的项目”,
输入:['items'];//已添加
模板:`
{{state}}
`
})
导出类MyItemComponent{
状态:boolean=false;
项目:项目[];//已添加
}
然后,您与


要在
items
更改implement
ngOnChanges()时在
MyItemComponent
中调用代码,请参见

导出类MyItemComponent{
状态:boolean=false;
项目:项目[];//已添加
ngOnChanges(更改:{[propName:string]:SimpleChange}){
log('ngOnChanges-myProp='+changes['items'].currentValue);
}
}

正如@Günter所说,这完全是真的

也就是说,我发现您的plunkr中存在一些错误:

@Component({
  selector: 'my-item',
  template: `
    <div>Hello</div>
  `
});  // <------- Remove the ;
export class MyItemComponent {

}
编辑

您可以利用
@ViewChildren
装饰器直接引用子对象

@Component({
  selector: 'my-app',
  template: `
    (...)
  `,
  directives: [MyItemComponent]
})
export class App {
  (...)
  @ViewChildren(MyItemComponent)
  children:MyItemComponent[];
  (...)
}
然后,您可以将控件添加到复选框中,以检测更改并相应地更新子组件的状态:

@Component({
  selector: 'my-app',
  template: `
    <div style="border: 1px solid red;">
      <label><input type="checkbox" [(ngModel)]="state"  
            [ngFormControl]="stateCtrl"/> {{state}}</label>
    </div>
    <div *ngFor="#item of items">
      <my-item></my-item>
    </div>
  `,
  directives: [MyItemComponent]
})
export class App {
  (...)
  constructor() {
    this.items.push(new Item("hello"));
    this.items.push(new Item("test"));

    this.stateCtrl = new Control();
    this.stateCtrl.valueChanges.subscribe(
      data => {
        this.children._results.forEach(child => {
          child.state = data;
        });
      });
  }
}
@组件({
选择器:“我的应用程序”,
模板:`
{{state}}
`,
指令:[MyItemComponent]
})
导出类应用程序{
(...)
构造函数(){
this.items.push(新项(“hello”);
此.items.push(新项(“测试”));
this.stateCtrl=新控件();
this.stateCtrl.valueChanges.subscribe(
数据=>{
this.children.\u results.forEach(child=>{
child.state=数据;
});
});
}
}
我使用以下方法更新了您的plunkr:


有关更多详细信息,请参阅此链接:

我想我忘记了在粘贴链接之前将最后更改保存到Plunkr。请看现在的更新。我不确定这些解决方案是我想要实现的。当我勾选/取消勾选红色内的复选框时,我希望两个/所有孩子也更新他们的状态。哦!我使用基于
@ViewChildren
装饰器和表单控件的方法分叉并更新了您的plunkr。我用它的描述更新了我的答案…有趣的方法,但它要求应用程序组件的逻辑与子组件的模板保持同步——即,应用程序逻辑需要知道子组件的模板正在使用
状态
属性。这是非常紧密的耦合,因此相当脆弱。最好使用输入属性,作为子组件的公共API。另一种减少耦合的方法(使用您的方法)是向子组件添加一个方法,该方法设置内部
状态
属性。然后应用程序组件可以调用公共API方法,而不是直接修改
状态
。我不需要检测数组中的更改。我只需要子组件能够检测到对父“状态”布尔值的更改。这是相同的原理,但您不需要切片和
ngochanges()
ok,谢谢您的输入。我现在使用组件的“属性”使用它。
properties
inputs
的不推荐的前身。
@Component({
  selector: 'my-app',
  template: `
    <div style="border: 1px solid red;">
      <label><input type="checkbox" [(ngModel)]="state"  
            [ngFormControl]="stateCtrl"/> {{state}}</label>
    </div>
    <div *ngFor="#item of items">
      <my-item></my-item>
    </div>
  `,
  directives: [MyItemComponent]
})
export class App {
  (...)
  constructor() {
    this.items.push(new Item("hello"));
    this.items.push(new Item("test"));

    this.stateCtrl = new Control();
    this.stateCtrl.valueChanges.subscribe(
      data => {
        this.children._results.forEach(child => {
          child.state = data;
        });
      });
  }
}