#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)
так как она в любом случае будет доступна в магазине.