Angular - изменение Input() из дочернего компонента не уведомляет родителя о том, что он был обновлен

У меня есть родительский компонент, который передает некоторые данные (selectedId) дочернему компоненту, используя @Input().

Родительский шаблон

<child-component [selectedId]="selectedId"></child-component>

Дочерний компонент использует selectedId следующим образом:

Дочерний шаблон

<select [(ngModel)]="selectedId">
  <option [value]="option.id" *ngFor="let option of options">{{option.name}}</option>
</select>

Дочерний компонент

export class HelloComponent  {
  @Input()
    set selectedId(id: any) {
      this._selectedId = id;
  }
  get selectedId() {
    return this._selectedId;
  }

  public _selectedId;

  options = [
      {
        "id": "1",
        "name": "Weekly"
      },
      {
        "id": "2",
        "name": "Bi-Weekly"
      },
      {

        "id": "3",
        "name": "Lunar"
      },
      {
        "id": "4",
        "name": "Monthly"
      }
  ]
}

Это работает отлично. Проблема в том, что я меняю выбранный элемент прямо из дочернего компонента, не используя родительский компонент.

Это следующий сценарий, когда он не работает должным образом:

  1. selectedId заполняется из родительского компонента (вызов API)
  2. Использование вручную изменяет параметры выбора (из child-component)
  3. API вызывается снова, и он должен установить тот же идентификатор, что и на шаге 1. Однако это не вызывает событие изменения. Я предполагаю, что родительский компонент не знает о ручном изменении, сделанном в дочернем компоненте, поэтому он по-прежнему содержит ссылку на selectedId из шага 1 и не запускает изменение на шаге 3, потому что это тот же идентификатор.

Я воссоздал проблему на Stackblitz

Я знаю, что могу использовать Output() и общие службы для решения этой проблемы, но есть ли другой способ сообщить родителю об обнаружении изменений?


person Dino    schedule 29.08.2019    source источник
comment
Это можно сделать с помощью EventEmitter. Я изменил ваш блиц стека, чтобы предоставить решение. Пожалуйста, взгляните на это. Надеюсь, поможет. stackblitz.com/edit/angular-32ckgk?file= источник/приложение/   -  person Suhas Parameshwara    schedule 29.08.2019


Ответы (2)


вы можете использовать @Output для уведомления родительского компонента об изменении в дочернем компоненте примерно так


@Component({
  selector: 'hello',
  templateUrl: './hello.component.html',
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input()
    set selectedId(id: any) {
      this._selectedId = id;
      console.log('Child change event --> ', id);
  }
  get selectedId() {
    return this._selectedId;
  }

  @Output() selectedIdChange=new EventEmitter();

  public _selectedId;

  options = [
      {
        "id": "1",
        "name": "Weekly"
      },
      {
        "id": "2",
        "name": "Bi-Weekly"
      },
      {
        "id": "3",
        "name": "Lunar"
      },
      {
        "id": "4",
        "name": "Monthly"
      }
  ]
  onChangeSelectedId(){
    this.selectedIdChange.emit(this.selectedId);
  }
}

и установите значение, подобное этому

<hello [(selectedId)]="selectedId"></hello>

person h_w    schedule 29.08.2019

Подход 1: добавьте эту переменную в общий сервис и используйте ее оттуда. Он будет обновляться всякий раз, когда ребенок или родитель изменяет его.

Подход 2: передать ввод от родителя к дочернему и добавить эмиттер событий, поэтому всякий раз, когда значения изменяются в дочернем, вы должны генерировать событие для обновления значения в родительском компоненте.

person Barkha    schedule 29.08.2019