So I'm fetching an observable array of custom IPix objects (Observable<IPix[]>) from a db (via an API) and then updating a record in the db by passing an edited copy of the IPix object back to the API in a PUT request (based on legacyConfigTrackerId).
I want to know how to replace the original IPix object in the array currently being displayed with the altered copy (based on legacyConfigTrackerId) so that the changes to the record will be reflected in the table right away without having to search/refresh.
Right now I can't even figure out how to filter the array, the result of the filter keeps coming back undefined and then nothing is displayed:
pixRecords$!: Observable<IPix[]>;
updatePix(pix: IPix) {
console.log('update clicked');
this.pixRecords$ =
this.pixRecords$.pipe(
map((records: IPix[]) =>
records.filter((p: IPix) => {
p.legacyConfigTrackerId !== pix.legacyConfigTrackerId
// need to do something to replace original object in array with the 'pix' argument
})
)
);
pix.contract.effectiveDate = this.revertEffDateFormat();
pix.contract.termDate = this.revertTermDateFormat();
this.pixService.putPix(pix);
this.formattedEffDate = '';
this.formattedTermDate = '';
this.closeModal.next(null);
}
I'm new to Angular so maybe my approach is all wrong, I'm open to suggestions.
When you are working with Observables, values are emitted and then gone. You can't treat a variable holding an Observable like other variables. You shouldn't really assign it to something (like this: this.pixRecords$ = this.pixRecords$.pipe(...)
).
You instead need to either:
For the second option, there are several approaches:
Here is an example of using the scan operator:
products$ = this.http.get<Product[]>(this.productsUrl)
.pipe(
tap(data => console.log('Products: ', JSON.stringify(data))),
catchError(this.handleError)
);
private productInsertedSubject = new Subject<Product>();
productInsertedAction$ = this.productInsertedSubject.asObservable();
allProducts$ = merge(
this.products$,
this.productInsertedAction$
).pipe(
scan((acc, value) =>
(value instanceof Array) ? [...value] : [...acc, value], [] as Product[])
)
Here the retrieved products are emitted into the products$
Observable. But the UI binding will be to the allProducts
Observable.
The productInsertedAction
emits any newly added product. The addProducts$
Observable then re-emits any time a new product is added.
The scan
operator retains the prior array of products, so this code is able to reference that (as the acc
variable) and add to it.
This code could be expanded to include update and delete operations.
You mentioned that you were new to Angular. I have an intro to RxJS video that you can find here if you want to dive a bit deeper into the basics: https://youtu.be/vtCDRiG__D4