Angular

#angular #ngrx #angular-ngrx-data #ngrx-data

Вопрос:

Я использую Angular 11 amp; NgRx-Данные 10.1.2. Я использую шаблон интеллектуального компонента/немого компонента.

В моем представлении «список», когда я выбираю элемент, я направляюсь на страницу сведений, передавая идентификатор элемента.

На моей странице сведений я подписываюсь на службу сущностей getByKey()

 this.siteEntityService.getByKey(this.siteId).subscribe((site: Site) => {
  this.site = site;
});
 

Это сайт сервиса:

 import { Injectable } from '@angular/core';
import { EntityCollectionServiceBase, EntityCollectionServiceElementsFactory } from '@ngrx/data';
import { Site } from 'src/app/models/site.model';

@Injectable({ providedIn: 'root' })
export class SiteEntityService extends EntityCollectionServiceBase<Site> {
  constructor(serviceElementsFactory: EntityCollectionServiceElementsFactory) {
    super('Site', serviceElementsFactory);
  }
}
 

Когда нажата кнопка «редактировать», я открываю компонент редактирования в модальном:

 openEditModal(){
  this.showingModal = true;

  this.modalRef = this.modalService.open(SiteEditShellComponent);
  this.modalRef.componentInstance.site = this.site;
}
 

В компоненте Редактирования при отправке формы нажимается:

   formSubmitted(form: any) {
    let updatedSite = { ...this.site };
    updatedSite.name = form.siteName;

    this.siteEntityService.update(updatedSite).subscribe((x: Site) => {
      this.site = x;
      this.activeModal.dismiss();
    })
  }
 

После обновления, если я исследую магазин, я вижу, что объект был обновлен правильно, однако после закрытия модала подписка на странице отображения не обновляется, несмотря на обновление магазина (и базы данных).

Так в чем же я ошибаюсь? Как мне получить страницу отображения для обновления данных?

Отредактировано в ответ на ответ @Fiber:

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

   loadSite() {
    let sites$ = this.siteEntityService.store.select((new EntitySelectorsFactory().create<Site>('Site')).selectEntities);

    this.subscriptions.add(
      sites$.pipe(
        map((sites: Site[]) => {
          return sites.find((site: Site) => site.id === this.siteId);
        })
      ).subscribe((site: Site) => {
        this.site = site;
      })
    );

    this.siteEntityService.getByKey(this.siteId).subscribe((site: Site) => {
      this.site = site;
    });
  }
 

Комментарии:

1. Что у тебя внутри this.siteEntityService.update ?

2. Я использую данные NgRx ( ngrx.io/guide/data ) модуль таким образом, мой сервис siteEntityService является расширением EntityCollectionServiceBase. Я обновил сообщение, чтобы показать это.

Ответ №1:

Сработает только один раз, когда он получит данные из серверной части:

 this.siteEntityService.getByKey(this.siteId).subscribe((site: Site) => {
  this.site = site;
});
 

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

Вы должны создать наблюдаемый объект, который напрямую подключается к хранилищу (ngrx/data предоставляет вам объект EntitySelectorsFactory, чтобы иметь возможность это сделать), и прослушивать изменения.

 // this is gonna fire every time you update the store with new 'Site' items
sites$ = this.store.select((new EntitySelectorsFactory().create<Site>('Site')).selectEntities);

sites$.subscribe((sites: Site[]) => {
  this.site = sites.find(s => s.id === this.siteId);
});

// this will trigger the initial load
this.siteEntityService.getByKey(this.siteId);
 

Очевидно, что подписки должны быть прекращены при уничтожении компонентов, но для краткости пропустили эту часть.

Комментарии:

1. У меня это работает, но у меня есть небольшой запрос по этому поводу, я обновил сообщение с дополнительной информацией.

2. Обновил свой ответ, вы правы, я допустил ошибку — сайты$ observable возвращаются с массивом сайтов, а не только с одним. Ваше решение для фильтрации карт кажется немного переполненным, либо используйте .pipe(карта(сайты => сайты.найти(s =>> s.id === this.SiteID))) или отфильтруйте его в подписке, как в обновленном примере.

3. Обновлено еще раз, вам не нужна подписка, this.siteEntityService.getByKey(this.siteId) так как она в любом случае будет доступна в магазине.