我有一个父组件,它通过服务从服务器获取数据 . 我需要将一些数据传递给Child组件 .
我一直试图用通常的 @Input()
传递这些数据,但是正如我预期的那样,我在Child组件中得到的数据是 undefined
.
Example
父组件
@Component({
selector: 'test-parent',
template: `
<test-child [childData]="data"></test-child>
`
})
export class ParentComponent implements OnInit {
data: any;
ngOnInit() {
this.getData();
}
getData() {
// calling service and getting data
this.testService.getData()
.subscribe(res => {
this.data = res;
});
}
}
子组件
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnInit {
@Input() childData: any;
ngOnInit() {
console.log(childData); // logs undefined
}
}
我保持简单的例子,以显示我正在尝试做的事情 . 我的问题是,在初始化之后是否可以将数据传递给孩子 . 我不确定但在这种情况下双向数据绑定会有帮助吗?
More Investigation
根据发布的答案,我尝试使用 ngOnChanges
生命周期钩子 . 我遇到的问题是,在更新数据时不会触发 ngOnChanges
函数 . 数据是一个对象,这就是我认为没有检测到更改的原因 .
更新了子组件中的代码
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnChanges {
@Input() childData: any;
ngOnChanges() {
console.log(childData); // logs undefined
}
}
我更新了OnChangesComponent以传递一个对象,在更新对象时,示例中可以看到ngOnChanges未检测到更改 . (这也显示在question中)
https://plnkr.co/edit/KkqwpsYKXmRAx5DK4cnV
似乎 ngDoCheck
可以帮助解决这个问题,但在我看来,从长远来看它不会有助于性能,因为这个Lifecycle Hook会检测到每个变化 .
另外我知道我可以使用 @ViewChild()
来访问子组件并设置我需要的变量,但我不认为对于这个用例它更有意义 .
Posting more code to help explain better
父组件
@Component({
selector: 'test-parent',
template: `
<test-child [childType]="numbers" [childData]="data" (pickItem)="pickNumber($event)">
<template let-number>
<span class="number" [class.is-picked]="number.isPicked">
{{ number.number }}
</span>
</template>
</test-child>
<test-child [childType]="letters" [childData]="data" (pickItem)="pickLetter($event)">
<template let-letter>
<span class="letter" [class.is-picked]="letter.isPicked">
{{ letter.displayName }}
</span>
</template>
</test-child>
<button (click)="submitSelections()">Submit Selection</button>
`
})
export class ParentComponent implements OnInit {
data: any;
numbersData: any;
lettersData: any;
ngOnInit() {
this.getData();
}
getData() {
// calling service and getting data for the game selections
this.testService.getData()
.subscribe(res => {
this.data = res;
setChildData(this.data);
});
}
setChildData(data: any) {
for(let i = 0; i < data.sections.length; i++) {
if(data.sections[i].type === 'numbers') {
this.numbersData = data.sections[i];
}
if(data.sections[i].type === 'letters') {
this.lettersData = data.sections[i];
}
}
}
pickNumber(pickedNumbers: any[]) {
this.pickedNumbers = pickedNumbers;
}
pickLetter(pickedLetters: any[]) {
this.pickedLetters = pickedLetters;
}
submitSelections() {
// call service to submit selections
}
}
子组件
@Component({
selector: 'test-child',
template: `
<!--
Content for child...
Showing list of items for selection, on click item is selected
-->
`
})
export class ChildComponent implements OnInit {
@Input() childData: any;
@Output() onSelection = new EventEmitter<Selection>;
pickedItems: any[];
// used for click event
pickItem(item: any) {
this.pickedItems.push(item.number);
this.onSelection.emit(this.pickedItems);
}
}
这或多或少都是我的代码 . 基本上我有一个处理子组件选择的父级,然后我将这些选择提交给服务 . 我需要将某些数据传递给孩子,因为我试图让孩子以服务所期望的格式返回该对象 . 这将有助于我不创建父组件中服务所期望的整个对象 . 此外,它会使子项重用,因为它会发回服务所期望的内容 .
Update
我感谢用户仍然在这个问题上发布答案 . 请注意,上面发布的代码对我有用 . 我遇到的问题是,在一个特定的模板中,我有一个错字导致数据为 undefined
.
希望它证明是有帮助的:)
5 回答
由于数据在开始时未定义,您可以使用* ngIf ='data'推迟数据
或者,您可以在组件上实现ControlValueAccessor,并使用ngModelChange通过ngModel传递它
您可以使用
ngOnChanges
获取如下数据,OnChanges
阅读更多相关信息here .
Update
ngOnChanges
只会在您更改整个对象时触发,如果您只想更新绑定对象的属性而不是整个对象有两个选项,要么直接在模板中绑定属性,请确保使用
?
,如{{childData?.propertyname}}
或者你可以根据childdata对象创建一个get属性,
Copmlete示例,
这是Plunker!
希望这可以帮助!!
当你的ChildComponent(你也称它为ParentComponent,但我猜它是一个错字)被初始化并执行其ngOnInit时,你的父级中没有数据可用,因为你的服务仍然无法获取你的数据 . 一旦您的数据存在,它将被推送给孩子 .
你能做什么取决于你的用例..
如果您只想在ChildComponent template 中显示数据,可以使用elvis运算符(
?
) . 类似的东西:{{ childData?}}
或{{ childData?.myKeyName }}
......如果你想做其他一些事情,你可以在你的ChildComponent中使用 setter . 它会截取输入变化,并让你有机会在你的ChildComponent中用它做其他事情之前用它来改变/测试/ "do what ever you want" . 例如:
或者像Madhu提到的那样使用
ngOnChanges
.您还可以在官方文档中查看Component Communication的cookbook条目 .
这应该是这样的吗?我希望这可能是问题所在
我假设孩子正在获取父项数据的子集,可能来自用户操作(例如,当用户单击网格行时加载表单) . 在这种情况下,我会使用一个事件 .
让父级激活一个事件,可能是dataSelected,事件的内容将是所选的数据 .
然后让孩子监听这些事件,并在被触发时将事件中的数据加载到模型中 .
这将有助于解耦您的组件,这总是一个好主意 .