асинхронный канал отправляет нулевое значение дочернему компоненту

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

<child [test]="test$ | async"></child>

test $ - это обычная наблюдаемая переменная, которая выдает значения через определенный период времени (3000 мс), имитируя запрос API к серверу.

this.test$=timer(3000).pipe(
      mapTo("value")      
 )

в дочернем компоненте я просто хочу проверить значение test

@Input() test: any;

constructor(){
    console.log("child/test", this.test); //null
    setTimeout(()=>console.log("child/test (timeout)", this.test),4000) //value

   if(this.test){
     //maintain and check `this.test`
     //this code will not run, because at this point `this.test` is null.
     //we don't know the exact time that `this.test` will have a value
     //this causes that `this.test` is wrong

      this.checked=true 
     }
  }

<div *ngIf="checked">{{test}}</div>

Я не хочу менять тип теста на Observable и подписываться на него. Я хочу получить окончательное значение напрямую. и я вообще не хочу изменять компонент редактирования.

использование ChangeDetectorRef для ручного запуска детектора изменений не

@Input() test$:Observable

constructor(){
  this.test$.subscribe(v=>this.test=v)
}

Я также сделал этот stackblitz, чтобы проверить изменение значения среди всех крючков компонента.


person Sh eldeeb    schedule 08.05.2020    source источник


Ответы (3)


app.component.html

<ng-container *ngIf=(test$ | async) as test; else defaultTmpl>
    <child [test]="test"></child>
</ng-container>
<ng-template #defaultTmpl>Default Template<ng-template>

Для получения дополнительных сведений посетите: https://ultimatecourses.com/blog/angular-ngif-async-pipe

person Alexander    schedule 08.05.2020
comment
это очень хорошая идея, но на самом деле я хочу отправить test непосредственно дочернему компоненту, даже если он еще не имеет значения. это заставляет дочерний компонент отображать шаблон по умолчанию до тех пор, пока test не получит его значение без необходимости самостоятельно реализовывать шаблон по умолчанию в моем родительском компоненте. - person Sh eldeeb; 08.05.2020
comment
Хорошо, еще одно решение - использовать ловушку ngOnChanges() для отслеживания изменений в вашем @Input(). Это внесет незначительные изменения в дочерний компонент, однако вы можете правильно отслеживать параметры ввода. Взгляните, пожалуйста: dev.to/nickraphael/ < / а> - person Alexander; 08.05.2020
comment
@Alexander - Обратите внимание, что он вообще не хочет изменять дочерний компонент. - person ConnorsFan; 08.05.2020
comment
@ConnorsFan - в любом случае он должен внести некоторые коррективы из-за того, что он хочет применить переключение между default шаблоном и шаблоном с данными в дочернем компоненте - person Alexander; 08.05.2020

async pipe вернет null, если Observable еще не отправил значение. Итак, значение test в дочернем компоненте:

  • undefined в конструкторе, потому что @Input() переменные не назначаются в этом состоянии
  • null после этого (например, первая onChanges ловушка или onInit ловушка), когда Observable не передает никакого значения
  • value когда Observable испускает новое значение

Теперь вы должны либо создавать дочерний компонент только тогда, когда test переменная не null с *ngIf, либо правильно обрабатывать состояние дочернего компонента с обнуляемым test (например, добавлять индикатор выполнения, когда test имеет значение null). Выбор остается за вами.

person HTN    schedule 08.05.2020

Вы можете создать переменную внутри своего шаблона следующим образом:

test$ | async; let test;

то позже вы можете проверить:

*ngIf='test'

если это правда, вы можете визуализировать свой дочерний компонент.

person KamLar    schedule 08.05.2020
comment
Внутри вашего родительского компонента. Затем вы используете просто ngIf, чтобы проверить, является ли test чем-то другим, кроме undefined или null, и если да, вы передаете его дочернему компоненту. - person KamLar; 08.05.2020