Dan*_*ima 34 angular-components angular
我有一个父组件,它通过服务从服务器获取数据.我需要将一些数据传递给Child组件.
我一直试图通过常规传递这些数据,@Input()但正如我所期望的那样,我在Child组件中得到的数据是undefined.
例
父组件
@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;
});
}
}
Run Code Online (Sandbox Code Playgroud)
子组件
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnInit {
@Input() childData: any;
ngOnInit() {
console.log(childData); // logs undefined
}
}
Run Code Online (Sandbox Code Playgroud)
我保持简单的例子,以显示我正在尝试做的事情.我的问题是,在初始化之后是否可以将数据传递给孩子.我不确定,但在这种情况下,双向数据绑定会有帮助吗?
更多调查
根据发布的答案,我尝试使用ngOnChanges生命周期钩子.我遇到的问题是在ngOnChanges更新数据时不会触发该函数.数据是一个对象,这就是我认为没有检测到更改的原因.
更新了子组件中的代码
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnChanges {
@Input() childData: any;
ngOnChanges() {
console.log(childData); // logs undefined
}
}
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用来自Angular团队的Popnker上的Live Examples进行测试,展示Lifecycle Hooks.在测试中,我更新了OnChangesComponent以传递一个对象,在更新对象时,示例中可以看到ngOnChanges未检测到更改.(这也显示在这个问题中)
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
}
}
Run Code Online (Sandbox Code Playgroud)
子组件
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
这或多或少都是我的代码.基本上我有一个父处理子组件的选择,然后我将这些选择提交给服务.我需要将某些数据传递给孩子,因为我试图让孩子以服务所期望的格式返回该对象.这将有助于我不创建父组件中服务所期望的整个对象.此外,它会使子项重用,因为它会发回服务所期望的内容.
更新
我感谢用户仍然在这个问题上发布答案.请注意,上面发布的代码对我有用.我遇到的问题是,在一个特定的模板中,我有一个错字导致了数据undefined.
希望它证明是有帮助的:)
Mop*_*opa 29
由于数据在开始时未定义,您可以使用*ngIf ='data'推迟它
<div *ngIf='data'>
<test-child [childData]="data"></test-child>
</div>
Run Code Online (Sandbox Code Playgroud)
或者,您可以在组件上实现ControlValueAccessor,并通过ngModel和ngModelChange传递给它
<test-child [ngModel]="data?" (ngModelChange)="data? ? data= $event : null"></test-child>
Run Code Online (Sandbox Code Playgroud)
Mad*_*jan 16
你可以ngOnChanges用来获取如下数据,
ngOnChanges() {
if(!!childData){
console.log(childData);
}
}
Run Code Online (Sandbox Code Playgroud)
OnChanges
Angular在检测到组件(或指令)的输入属性发生更改时调用其ngOnChanges方法.
在这里阅读更多相关信息.
更新
ngOnChanges 只有在你改变整个对象时才会触发,如果你只想更新绑定对象的属性而不是整个对象你有两个选项,
要么直接在模板中绑定属性,请确保使用?like{{childData?.propertyname}}
或者你可以根据childdata对象创建一个get属性,
get prop2(){
return this.childData.prop2;
}
Run Code Online (Sandbox Code Playgroud)Copmlete示例,
import { Component, Input } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>
<child-component [childData]='childData' ></child-component>
`
})
export class AppComponent {
name = 'Angular';
childData = {};
constructor(){
// set childdata after 2 second
setTimeout(() => {
this.childData = {
prop1 : 'value of prop1',
prop2 : 'value of prop2'
}
}, 2000)
}
}
@Component({
selector: 'child-component',
template: `
prop1 : {{childData?.prop1}}
<br />
prop2 : {{prop2}}
`
})
export class ChildComponent {
@Input() childData: {prop1: string, prop2: string};
get prop2(){
return this.childData.prop2;
}
}
Run Code Online (Sandbox Code Playgroud)
这是Plunker!
希望这可以帮助!!
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnChanges {
@Input() childData: any;
ngOnChanges() {
console.log(childData); // logs undefined
}
}
Run Code Online (Sandbox Code Playgroud)
这应该是这样的,不是吗?我希望这可能是问题所在。
ngOnChanges() {
console.log(this.childData); // reference with this
}
Run Code Online (Sandbox Code Playgroud)
当您的 ChildComponent(您也称它为 ParentComponent,但我想这是一个错字)初始化并执行其 ngOnInit 时,您的父组件中没有可用的数据,因为您的服务仍将无法获取您的数据。一旦您的数据在那里,它将被推送给孩子。
您可以做什么取决于您的用例..
如果您只想显示 ChildComponent模板中的数据,您可以使用 elvis 运算符 ( ?)。类似的东西:{{ childData?}}或{{ childData?.myKeyName }}...
如果你想做一些其他的事情,你可以在你的 ChildComponent 中使用一个setter。它将拦截输入更改并让您有机会在您的 ChildComponent 中使用它做其他事情之前改变/测试/“做任何你想做的事情”。例如:
@Component({
selector: 'test-child',
template: `
<!-- Content for child.... -->
`
})
export class ChildComponent implements OnInit {
private _childData: any;
@Input()
set childData(parentData: any) {
// every time the data from the parent changes this will run
console.log(parnetData);
this._childData = parentData; // ...or do some other crazy stuff
}
get childData(): any { return this._childData; }
ngOnInit() {
// We don't need it for that...
}
}
Run Code Online (Sandbox Code Playgroud)
或ngOnChanges像 Madhu 提到的那样使用。
您可能还想查看官方文档中组件通信的说明书条目。
| 归档时间: |
|
| 查看次数: |
50183 次 |
| 最近记录: |