Felix
Felix

Reputation: 1810

How to force ngrx-data to clear cached entities and reload data from db

I have a typical ngrx-data arrangement of 'User' entities linked to db. I implement the standard service to handle the data:

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

I read the data using:

this.data$ = this.userService.getAll();
this.data$.subscribe(d => { this.data = d; ... } 

Data arrives fine. Now, I have a GUI / HTML form where user can make changes and update them. It also works fine. Any changes user makes in the form are updated via:

this.data[fieldName] = newValue;

This updates the data and ngrx-data automatically updates the entity cache.

I want to implement an option, where user can decide to cancel all changes before they are written to the db, and get the initial data before he made any adjustments. However, I am somehow unable to overwrite the cached changes.

I tried:

this.userService.clearCache();
this.userService.load();

also tried to re-call:

this.data$ = this.userService.getAll();

but I am constantly getting the data from the cache that has been changed by the user, not the data from the db. In the db I see the data not modified. No steps were taken to write the data to db.

I am not able to find the approach to discard my entity cache and reload the original db data to replace the cached values.

Any input is appreciated.

Upvotes: 0

Views: 1734

Answers (1)

hunter
hunter

Reputation: 1

You will need to subscribe to the reassigned observable when you change this.data$, but it will be a bit messy.

First you bind this.data$ via this.data$ = this.userService.entities$, then no matter you use load() or getAll(), as long as the entities$ changed, it fire to this.data$.subscribe(). You can even skip the load and getAll if you already did that in other process.

You can then use the clearCache() then load() to reset the cache.

But I strongly recommand you to keep the entity data pure. If the user exit in the middle without save or reset, the data is changed everywhere you use this entity.

My recommand alternatives:

(1) Use angular FormGroup to set the form data with entity data value, then use this setting function to reset the form.

(2) Make a function to copy the data, then use this copy function as reset.

For example using _.cloneDeep.

(2.1) Using rxjs BehaviourSubject:

resetTrigger$ = new BehaviourSubject<boolean>(false);

ngOnInit(){
    this.data$ = combineLastest([
        this.resetTrigger$,
        this.userService.entities$
    ]).subscribe([trigger, data])=>{
        this.data = _.cloneDeep(data)
    });
 
    // can skip if already loaded before
    this.userService.load();
}

When you want to reset the data, set a new value to the trigger

resetForm(){
    this.resetTrigger$.next(!this.resetTrigger$.value)
}

(2.2) Using native function (need to store the original):

this.data$ = this.userService.entities$.pipe(
    tap(d=>{
        this.originData = d;
        resetForm();
    })
).subscribe()

resetForm:

resetForm:()=>{
    this.data = _.cloneDeep(this.originData);
}

Upvotes: 0

Related Questions