Mam dane, które wyciągam z mojego serwera w oparciu o określoną datę. Więc kiedy data zmienia się ponownie z serwera, aby uzyskać nowe dane. Mam również możliwość ręcznego wyzwalania odświeżania z serwera (w przypadku przypadków, gdy ciągnąłem dane, więc muszę ponownie wyciągnąć)

private _date = new BehaviorSubject(new Date())
private _refresh = new BehaviorSubject<void>(undefined); 
readonly data$: Observable<Model[]> = combineLatest([this._date, this._refresh])
   .pipe( 
      switchMap(([date, refresh]) => this.dataService.get(date)),
      shareReplay(1) 
   )

Mój widok jest wyświetlany data$ za pomocą rury asynchronicznej

Muszę być w stanie manipulować listą w data$, dzięki czemu mogę śledzić zmodyfikowane elementy na liście.

Model {
   ...
   isModified: boolean
}

Mój model jest taki, więc jeśli dokonam zmiany elementu Chcę być w stanie nacisnąć to do listy danych (usuń stary przedmiot - & GT; Wymień za pomocą nowego zmodyfikowanego elementu), a następnie mają data$ emituj aktualizację lista.

Następnie jeśli _date emituje $data emitują, że i wszystko zmodyfikowane zostanie wymazane.

Próbowałem nie zamuać elementów na liście bezpośrednio, więc mogę wykorzystać ChangeDetectionStrategy.OnPush

Czy istnieje sposób, w jaki mogę łączyć parę ręcznego aktualizacji listy i {x0}} aktualizowania listy, ale podczas ciągnięcia z serwera, który miał pierwszeństwo.


Tylko utrzymanie jednej listy powinno pozwolić mi łatwiej uzyskać agregaty oparte na danych. Ponieważ aktualizuj przedmioty moje agregujące wartości będą aktualizowane na podstawie modyfikowanej listy. Jeśli utrzymam drugą listę zmodyfikowanych przedmiotów, musiałbym porównać dwa listy, jeśli chciałem, aby agregować wartości w zmodyfikowanym stanie (zdobędę wszystkie elementy na głównej liście, które nie są modyfikowane i wszystkie przedmioty z modyfikowanej listy).

Aktualizacja wsadowa powinna być tak łatwa jak

data$.pipe(
   filter(x => x.isModified), 
   switchMap(x => dataService.update(x))
)

Oto a Stoitblitz że wierzę, że pomoże zademonstrować.

Tutaj możesz zobaczyć, że mam komponent, który pozwala na aktualizację nazwy przedmiotów zwróconych z mojego obserwowalnego. Chciałbym móc modyfikować te elementy, a następnie przechowywać je z powrotem do obserwowalnego. W ten sposób, gdybym chciał uzyskać wszystkie zmodyfikowane przedmiot, który mógłbym zastosować filtr, który obserwuje, aby uzyskać zmodyfikowane elementy. Ponadto, jeśli zmienisz datę, że obserwowalne zostanie odwrócone z serwera, a lista zmodyfikowanych elementów zostanie wymazana.

Patrz DataService.itemNameChanged

1
rpascal 29 lipiec 2020, 19:34

1 odpowiedź

Najlepsza odpowiedź

Aby rozwiązać ten problem, możesz użyć operatora skanowania, aby utrzymać wartość nowych elementów w tablicy.

Tutaj powstaje behachiorsubject, aby emitują wartości każdego nowego elementu zmodyfikowanego, jest inicjowany z pierwszą wartością domyślnej tablicy.

  private itemModified = new BehaviorSubject<Model>(data[0]);

Za każdym razem, gdy obserwowani na bazie DateFresh $ są aktualizowane tej wartości należy zresetować.

  readonly dateRefreshHttp$: Observable<Model[]> = combineLatest([
    this._date,
    this._refresh
  ]).pipe(
    tap(() => this.itemModified.next(data[0])),
    switchMap(([date, refresh]) =>

Operator skanowania jest dodawany wewnątrz przełącznika, w celu ponownego uruchomienia akumuluj, gdy się zmienia. Zwróć uwagę na odbicie operatora dodany, aby umożliwić wiele wprowadzania znaków bez utraty ostrości.

   switchMap(([date, refresh]) =>
      combineLatest([from([data]), this.itemModified]).pipe(
        scan(
          (acc: any[], [data, itemModified], index: number) => {
            return acc.map(item =>
              item.id == itemModified.id ? itemModified : item
            );
          },
          [...data]
        )
      )
    ),
    debounceTime(300)
  );

Wreszcie, nowa wartość jest emitowana przez zmianę nazwy elementu.

  itemNameChanged(newName: string, item: Model) {
    const newItem: Model = {
      id: item.id,
      name: newName,
      isModified: true
    };

    this.itemModified.next(newItem);
  }

Przykład na żywo, Stackblitz

1
bernatsampera 30 lipiec 2020, 13:15