Angular2 - 通知 child parent object 已更改,因此 child 可以在其模板内重新触发 ngIf
Angular2 - notify child that parent object changed so child can refire an ngIf inside its template
我有一个与 类似的问题,但似乎这个问题已经过时了,因为这两个答案都不适合我。
child 组件只是简单地呈现来自名为 Proposal
的复杂 object 的数据作为输入传递(它根本没有用户控件,因此不需要触发任何事件或传递任何东西)。
@Component({
selector: 'fb-proposal-document',
templateUrl: './proposal-document.component.html',
styleUrls: ['./proposal-document.component.css']
})
export class ProposalDocumentComponent implements OnInit, OnDestroy {
@Input() proposal: Proposal;
constructor()
}
模板的相关部分是这样的,迭代数组并检查 属性 以使用 *ngIf
:
显示不同的文本
<li class="section" *ngFor="let qp of proposal?.quoted_products">
<li class="section" *ngFor="let room of qp?.rooms">
...
<div class="row">
<div class="col-md-12">
Supply
<span *ngIf="room.is_fitted">
and install
</span>
<span *ngIf="!room.is_fitted">
only
</span>
</div>
</div>
...
</li>
</li>
在 parent 中,用户可以单击复选框将 'is_fitted' 更改为 true 或 false。 parent 使用的是 domain-drive 形式。在parent的ngOnInit
中是这样的代码:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
}
);
正确更新了 属性。我可以看到,如果我 console.log
它。所以问题是,当嵌入的 room.is_fitted
值发生变化时,如何将 child 变为 refire/re-process *ngIf
?
我已经尝试使用 ViewChild 实现 this idea,所以 ngOnInit 中的上述代码变为:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
this.proposalDocument.notifyChange(this.proposal);
}
);
但这也不起作用。我在child中的notifyChange调用成功:
notifyChange(proposal: Proposal) {
console.log('I changed');
this.proposal = proposal;
}
但视图没有更新 - *ngIf
逻辑没有得到重新处理。
更新
看我的另一个回答,因为现在看来这一切都没有必要了。但我会把它留在这里,因为它可能会对某人有所帮助。
根据@JBNizet 在问题评论中提供的link,我尝试了这个解决方案:
ngOnChanges(changes: SimpleChanges){
console.log('I changed ngOnChanges');
console.log(changes);
for (let propName in changes){
if (propName == 'is_fitted') {
this.proposal.quoted_products.forEach(function(qp) {
qp.rooms.forEach(function(room) {
room.is_fitted = changes[propName].currentValue;
});
});
}
};
};
因此,父级没有调用我的自定义 notifyChange,而是调用了这个 ngOnChanges 方法,如下所示:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
this.proposalDocument.ngOnChanges({
is_fitted: value
});
}
);
新值到达子项,我可以在控制台中看到它,属性 在模型上更新,视图 NOW 更新。
我想知道这是否有效,以及我是否应该在这个双循环之前和之后分离并重新连接,如下所示:
for (let propName in changes){
if (propName == 'is_fitted') {
console.log('detaching');
this.ref.detach();
this.proposal.quoted_products.forEach(function(qp) {
qp.rooms.forEach(function(room) {
room.is_fitted = changes[propName].currentValue;
});
});
this.ref.reattach();
this.ref.detectChanges();
}
};
this official guide 中有关 detectChanges()
的更多信息。
我把所有的代码都拿出来重新写了一遍,我的第一次尝试现在成功了:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
}
);
我根本不需要通知child。视图会自动更新。
我从阅读的所有内容中确信,复杂的 objects 不会更新深层属性 - 只有当您更改对 object 本身的引用时。但在这里,我现在正在更改深层属性,并且我没有通过调用 ngOnChanges 通知 child,并且它有效。去图吧。
我有一个与
child 组件只是简单地呈现来自名为 Proposal
的复杂 object 的数据作为输入传递(它根本没有用户控件,因此不需要触发任何事件或传递任何东西)。
@Component({
selector: 'fb-proposal-document',
templateUrl: './proposal-document.component.html',
styleUrls: ['./proposal-document.component.css']
})
export class ProposalDocumentComponent implements OnInit, OnDestroy {
@Input() proposal: Proposal;
constructor()
}
模板的相关部分是这样的,迭代数组并检查 属性 以使用 *ngIf
:
<li class="section" *ngFor="let qp of proposal?.quoted_products">
<li class="section" *ngFor="let room of qp?.rooms">
...
<div class="row">
<div class="col-md-12">
Supply
<span *ngIf="room.is_fitted">
and install
</span>
<span *ngIf="!room.is_fitted">
only
</span>
</div>
</div>
...
</li>
</li>
在 parent 中,用户可以单击复选框将 'is_fitted' 更改为 true 或 false。 parent 使用的是 domain-drive 形式。在parent的ngOnInit
中是这样的代码:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
}
);
正确更新了 属性。我可以看到,如果我 console.log
它。所以问题是,当嵌入的 room.is_fitted
值发生变化时,如何将 child 变为 refire/re-process *ngIf
?
我已经尝试使用 ViewChild 实现 this idea,所以 ngOnInit 中的上述代码变为:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
this.proposalDocument.notifyChange(this.proposal);
}
);
但这也不起作用。我在child中的notifyChange调用成功:
notifyChange(proposal: Proposal) {
console.log('I changed');
this.proposal = proposal;
}
但视图没有更新 - *ngIf
逻辑没有得到重新处理。
更新
看我的另一个回答,因为现在看来这一切都没有必要了。但我会把它留在这里,因为它可能会对某人有所帮助。
根据@JBNizet 在问题评论中提供的link,我尝试了这个解决方案:
ngOnChanges(changes: SimpleChanges){
console.log('I changed ngOnChanges');
console.log(changes);
for (let propName in changes){
if (propName == 'is_fitted') {
this.proposal.quoted_products.forEach(function(qp) {
qp.rooms.forEach(function(room) {
room.is_fitted = changes[propName].currentValue;
});
});
}
};
};
因此,父级没有调用我的自定义 notifyChange,而是调用了这个 ngOnChanges 方法,如下所示:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
this.proposalDocument.ngOnChanges({
is_fitted: value
});
}
);
新值到达子项,我可以在控制台中看到它,属性 在模型上更新,视图 NOW 更新。
我想知道这是否有效,以及我是否应该在这个双循环之前和之后分离并重新连接,如下所示:
for (let propName in changes){
if (propName == 'is_fitted') {
console.log('detaching');
this.ref.detach();
this.proposal.quoted_products.forEach(function(qp) {
qp.rooms.forEach(function(room) {
room.is_fitted = changes[propName].currentValue;
});
});
this.ref.reattach();
this.ref.detectChanges();
}
};
this official guide 中有关 detectChanges()
的更多信息。
我把所有的代码都拿出来重新写了一遍,我的第一次尝试现在成功了:
this.myForm.controls['isFitted'].valueChanges.subscribe(
value => {
this.proposal.is_fitted = value;
let qp = this.proposal.quoted_products[this.qpCurrentIndex];
qp.rooms.forEach(function(room) {
room.is_fitted = value;
});
}
);
我根本不需要通知child。视图会自动更新。
我从阅读的所有内容中确信,复杂的 objects 不会更新深层属性 - 只有当您更改对 object 本身的引用时。但在这里,我现在正在更改深层属性,并且我没有通过调用 ngOnChanges 通知 child,并且它有效。去图吧。