Как обновить изменения в дочернем компоненте

#angular #angular2-changedetection

#angular #angular2-обнаружение изменений

Вопрос:

@input Значение дочернего компонента не обновляет свое значение в html , как two-way обычно делает привязка. Вот мой код.

 parent.component.html

<app-child [i]="selectedMonth" (monthChanged)="monthChanged($event)"></app-child>

monthChanged(d: Date) {
    this.selectedMonth = d; // this is working as expected.
    console.error(this.selectedMonth); // working...
  }

child.component.html

<div>
    <span (click)="addMonth(-1)">Prev </span>
    <span>{{i | date:'MMM-yyyy'}}</span> // this value not being changed.
    <span (click)="addMonth(1)">Next </span>
</div>

child.component.ts

export class ChildComponent implements OnInit {
  @Input() i: Date;
  @Output() monthChanged = new EventEmitter<Date>();

  constructor() { }

  ngOnInit(): void {
  }

  addMonth = (m: number) => {
    this.i.setMonth(this.i.getMonth()   m);
    this.monthChanged.emit(this.i);
  }

}
  

Что я пробовал?

 this.changeDetectorRef.detectChanges();

ngOnChanges(changes: SimpleChanges) {
    console.error(this.i); // no error log...
    this.i = changes.i.currentValue;
    console.error(this.i); // no error log...
  }
  

Но ничего не работает. Что еще я должен использовать?

Ответ №1:

Я создал stackblitz, воспроизводящий вашу проблему. Вы можете проверить это здесь

Вы можете проверить журналы консоли. При обновлении внутри дочернего компонента с помощью this.i.setMonth(this.i.getMonth() m) он также обновляет parent s selectedMonth . Потому что они являются одним и тем же объектом. Поскольку ссылка на объект не изменяется, Angular не будет запускать обнаружение изменений. Вы можете исправить это, создав новый объект внутри monthChanged следующим образом

Изменить

 monthChanged(d: Date) {
  this.selectedMonth = d; 
  ...
}
  

Для

 monthChanged(d: Date) {
  this.selectedMonth = new Date(d); 
  ...
}
  

Ответ №2:

Данные будут обновлены, когда будет обновлена вся ссылка. Если вы просто обновите некоторые свойства внутри этого объекта, он не будет запущен. Вам нужно изменить ссылку на переданный объект.

Пример

 <child [data]="myData"></child>
  

Если вы обновите myData.test= "YourData", , это не сработает. Вам нужно что-то сделать

 this.myData = changedData;
  

Обходным путем может быть использование перехвата жизненного цикла doCheck и попытка проверить изменение свойства вручную. Но, как правило, удобнее изменить ссылку.

Проверьте свое значение здесь

  // on every change of @input 'name', this method will be triggered

  ngOnChanges() {
    this.data=changedData 
  }