1

我对这个问题有类似的问题,但似乎这个问题已经过时了,因为这两个答案都不适合我。

子组件只是从一个称为Proposal作为输入传递的复杂对象中呈现数据(它根本没有用户控件,因此不需要触发任何事件或传递任何东西)。

@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>

在父级中,用户可以单击复选框将“is_fitted”更改为 true 或 false。父级使用域驱动器形式。在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这样做。*ngIf所以问题是,当嵌入的room.is_fitted值发生变化时,如何让孩子重新触发/重新处理?

我已经尝试使用 ViewChild 实现这个想法,因此 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);
  }
);

但这也不起作用。我在孩子中的 notifyChange 被成功调用:

  notifyChange(proposal: Proposal) {
    console.log('I changed');
    this.proposal = proposal;
  }

但视图不会更新 -*ngIf逻辑不会被重新处理。

4

2 回答 2

1

我取出所有代码并从头开始重新编写,我的第一次尝试现在有效:

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;
    });
  }
); 

我根本不需要通知孩子。视图会自动更新。

从我所读到的所有内容中,我确信复杂对象不会更新深层属性 - 只有当您更改对对象本身的引用时。但是在这里,我现在正在更改深层属性,并且不会通过调用 ngOnChanges 来通知孩子,并且它可以工作。去搞清楚。

于 2017-01-14T09:46:26.303 回答
0

更新

请参阅我的其他答案,因为现在这一切似乎都没有必要。但我会把它留在这里,因为它可能会对某人有所帮助。


按照@JBNizet 在问题评论中提供的链接,我尝试了这个解决方案:

  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 
    });
  }
); 

新值到达子节点,我可以看到它记录在控制台中,模型上的属性已更新,视图现在已更新。

我确实想知道这是否有效,以及我是否应该在这个双循环之前和之后分离和重新连接,如下所示:

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();
  }
};

detectChanges()有关此官方指南的更多信息。

于 2017-01-14T01:34:28.147 回答