Я использую простой компонент для отображения текущего значения из моего магазина с помощью асинхронного канала (Angular 6). Значение из хранилища представляет собой простые объекты (без массива) для хранения текущего выбранного элемента, который должен отображаться компонентом средства просмотра.
<div *ngIf="(displayElement$ | async) as displayElement" class="content">
{{displayElement | json}}
<ng-container [ngSwitch]="displayElement.typ">
<!-- use a ng-container to group multiple root nodes -->
<dokument-viewer *ngSwitchCase="'Dokument'" #dokumentViewer [imageSize]="100" [zoomFactor]="0.1" [index]="0"
[externalId]="displayElement.externalId" [pageNumber]="1"></dokument-viewer>
</ng-container>
</div>
А в конструкторе компонентов код:
this.displayElement$ = this.store
.select(st => st.state.currentSelectedElement)
Все отлично работает.
Но когда я создаю компонент динамически (componentFactoryResolver), представление не получает никаких обновлений.
Используя точку останова, я вижу, что значение из магазина корректно обновляется.
Первая попытка:
this.displayElement$ = this.store
.select(st => st.state.currentSelectedElement)
.pipe(distinctUntilChanged(), tap(val => this.cd.detectChanges()));
Это что-то показывает. Но - действительно странно - это всегда на один шаг позади текущих данных магазина. Отображает «предыдущий» элемент.
Единственный код, который действительно работает, - это подписаться на магазин, управлять подпиской вручную и избавиться от асинхронного канала.
И, конечно же, с помощью DetectChanges.
Но мне стыдно, когда я пользуюсь этими методами (особенно обнаружения изменений).
Что я делаю не так, используя asing pipe.
Динамический код:
// create a factory for a new WsDashboardElementComponent
const factory = this.componentFactoryResolver.resolveComponentFactory(
WsDashboardElementComponent
);
// render content
const ngContent = this.resolveNgContent(contentToBeAdded);
// create an injector with providers
this.injector = Injector.create(
[{ provide: WsDashboardComponent, useValue: null }],
this.injector
);
// create the component with the content as second paramter
const componentDashBoardElementRef = factory.create(
this.injector,
ngContent
);
// copy filled properties
Object.keys(elementSettings).forEach(
key => elementSettings[key] == null && delete elementSettings[key]
);
Object.assign(componentDashBoardElementRef.instance, elementSettings); // { ...elementSettings };
// render updates
componentDashBoardElementRef.hostView.detectChanges();