Необъяснимое поведение наблюдаемого значения в форме Angular 5

Вот код компонента Angular, который можно запустить по адресу https://plnkr.co/edit/eEXt9JD3OO5rRl3p37Je?p=preview

@Component({
  selector: 'my-app',
  template: `
  <div  *ngIf="currentNumber$ | async as currentNumber">
    <b>{{currentNumber}}</b>
  </div>
  <form [formGroup]="simpleForm">
    <input type="number" formControlName="number" />
  </form>
  `,
})
export class App {
  primeNumbers$ : Observable<number>;
  simpleForm : FormGroup;
  constructor() {
    this.primeNumbers$ = Observable.from([3,5,7]);
    this.simpleForm = new FormGroup({
      number : new FormControl(1);
    })
  }
  get currentNumber$() : Observable<number>{
    return this.primeNumbers$.filter(n=>n===this.simpleForm.controls["number"].value);
  }
}

Он работает по желанию: когда я набираю одно из 3,5,7 чисел во входных данных формы, оно появляется в верхней части формы, что означает, что currentNumber$ observable IS обновляется, когда элемент управления "number" меняет свое значение. Как это вообще возможно? Как Angular понимает, когда обновлять наблюдаемое в этой ситуации? Допустим, асинхронный канал подписывается на наблюдаемый. Но как компонент понимает, что новое наблюдаемое значение должно передаваться при изменении значения элемента управления формы? есть только ссылка на элемент управления формы, и он глубоко скрыт в предикате фильтра

2 ответа

Волшебная смесь заключается в том, что вы используете async труба, которая делает оценку наблюдаемых для вас в html шаблон, он же подписывается на наблюдаемые и реагирует на излучение наблюдаемых.

Асинхронный канал подписывается на Observable или Promise и возвращает последнее выданное им значение. Когда выдается новое значение, асинхронный канал помечает компонент, который необходимо проверить на наличие изменений. Когда компонент уничтожается, асинхронный канал автоматически отписывается, чтобы избежать возможных утечек памяти.

Редактировать:

Причина, по которой ввод текста приводит к изменению html, немного сложна. Вам нужно будет понять крючки жизненного цикла Angular. Но здесь идет:

Это работает, потому что в тот момент, когда вы вводите значение в форму ввода, оно вызывает ngOnChanges() крючок жизненного цикла. Angular оценивает все привязки, включая эту *ngIf="currentNumber$ | async as currentNumber", Теперь, потому что ваш currentNumber$ собирается отфильтровать числа на основе current значение формы (которая к тому времени уже обновлена), следовательно, она показывает только отфильтрованные числа. Вот последовательность событий.

  1. Инициализация компонента
    • this.simpleForm.controls["number"].value содержит null
  2. Вы вводите в 5 на входе.
  3. Вы вызвали ngOnChange велосипедный крюк
  4. this.simpleForm.controls["number"].value теперь содержит 5
  5. Затем Angular переоценивает каждую привязку.
  6. currentNumber$() исполняется.
    • это фильтрует primeNumber$ основываясь на вашем this.simpleForm.controls["number"].value, который сейчас содержит 5
  7. Angular теперь обновляет все связанные свойства
  8. currentNumber$() функция возвращает 5, после фильтрации
  9. async труба подписывается на данные (которые уже есть)
  10. HTML показывает 5

currentNumber$ observable вызывается каждый раз, когда что-либо в форме изменяется. Попробуйте положить console.log в нем вроде

get currentNumber$() : Observable<number>{
  console.log("observable called")
  return this.primeNumbers$.filter(n=>n===this.simpleForm.controls["number"].value);
}

И вы увидите, что он вызывается не только при изменении ввода, но и при инициализации формы и т. Д.

Число, появляющееся / исчезающее, является просто результатом наблюдаемого фильтра, имеющего или не имеющего значения.

Другие вопросы по тегам