我一直试图用通常的@Input()传递这些数据,但是正如我所期望的那样,我在Child组件中得到的数据是未定义的。
例
父组件
@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 } }
我保持简单的例子,以显示我正在尝试做的事情。我的问题是,在初始化之后是否可以将数据传递给孩子。我不确定但在这种情况下双向数据绑定会有帮助吗?
更多调查
根据发布的答案,我尝试使用ngOnChanges生命周期钩子。我遇到的问题是更新数据时不会触发ngOnChanges函数。数据是一个对象,这就是我认为没有检测到更改的原因。
更新了子组件中的代码
@Component({ selector: 'test-child',template: ` <!-- Content for child.... --> ` }) export class ChildComponent implements OnChanges { @Input() childData: any; ngOnChanges() { console.log(childData); // logs undefined } }
我已经尝试使用Angular团队的Plunker上的Live Examples进行测试,展示Lifecycle Hooks。在测试中,我更新了OnChangesComponent以传递一个对象,在更新对象时,示例中可以看到ngOnChanges未检测到更改。 (这也在question中显示)
https://plnkr.co/edit/KkqwpsYKXmRAx5DK4cnV
似乎ngDoCheck可以帮助解决这个问题,但在我看来,从长远来看它不会有助于性能,因为这个Lifecycle Hook会检测到每个变化。
另外我知道我可以使用@ViewChild()来访问子组件并设置我需要的变量,但我不认为对于这个用例它更有意义。
发布更多代码以帮助解释更好
父组件
@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); } }
这或多或少都是我的代码。基本上我有一个处理子组件选择的父级,然后我将这些选择提交给服务。我需要将某些数据传递给孩子,因为我试图让孩子以服务所期望的格式返回该对象。这将有助于我不创建父组件中服务所期望的整个对象。此外,它会使子项重用,因为它会发回服务所期望的内容。
更新
我感谢用户仍然在这个问题上发布答案。请注意,上面发布的代码对我有用。我遇到的问题是,在一个特定的模板中,我有一个拼写错误导致数据未定义。
希望它证明是有帮助的:)
<div *ngIf='data'> <test-child [childData]="data"></test-child> </div>
或者,您可以在组件上实现ControlValueAccessor,并使用ngModelChange通过ngModel传递它
<test-child [ngModel]="data?" (ngModelChange)="data? ? data= $event : null"></test-child>