Угловой асинхронный канал не обновляет представление с помощью хранилища ngrx и динамического компонента - PullRequest
0 голосов
/ 02 ноября 2018

Я использую простой компонент для отображения текущего значения из моего магазина с помощью асинхронного канала (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();
...