angularangular-akitaakita

How should I structure my Angular service with Akita store?


I'm using Akita entity data stores to cache data on the front end of an Angular application.

In my service I have some functions something like this:

setPropertyOfEntity(entityId, newValue): void {
   store.update(entityId, {propertyName: newValue});
   this.saveEntity(store.getEntity(entityId));
}

saveEntity(entity) {
  httpClient.put(url, entity).subscribe((savedEntity) -> {
      store.upsert(savedEntity.id, savedEntity)
  });
}

Now, understandably, the Akita store kicks out a whole lot of events as the entity is updated in the store (property gets set, upsert after save).

I feel I want to update the store after save in case of side effects on the entity done by serverside logic (which does happen in this case).

What is the Akita-way when it comes to keeping FE/BE in sync like this?

I guess I could get the entity from the store, set value on it, then call the save function but that seems counter to what seems to be the Akita way of using store.update() to update properties on objects.

As Akita retuns immutables from its getEntity() function I end up with something that just feels wrong (assign(), not using akita builtin store.update())....

setPropertyOfEntity(entityId, newValue): void {
   let storeEntity = store.getEntity(entityId);
   let mutableEntity = Object.assign(new Entity(), storeEntity)
   mutableEntity.property = newValue;
   this.saveEntity(mutableEntity);
}

Solution

  • I got the problem you're talking about. I don't think Akita has any built in solution for such things. In my opinion you rather have an architectual propblem with all these methods that updates just one property.

    Let's say you have several functions that updates only one entity property, it will look like that:

    setProperty1OfEntity(entityId, newValue): void {
       let storeEntity = store.getEntity(entityId);
       let mutableEntity = Object.assign(new Entity(), storeEntity)
       mutableEntity.property1 = newValue;
       this.saveEntity(mutableEntity);
    }
    
    setProperty2OfEntity(entityId, newValue): void {
       let storeEntity = store.getEntity(entityId);
       let mutableEntity = Object.assign(new Entity(), storeEntity)
       mutableEntity.property2 = newValue;
       this.saveEntity(mutableEntity);
    }
    
    setProperty3OfEntity(entityId, newValue): void {
       let storeEntity = store.getEntity(entityId);
       let mutableEntity = Object.assign(new Entity(), storeEntity)
       mutableEntity.property3 = newValue;
       this.saveEntity(mutableEntity);
    }
    

    All these functions get the original entity, then update the required property and then save it - 3 of 4 lines of the code inside them are duplicated and even the only different line - mutableEntity.property3 = newValue; has just another name of the entity field...

    It doesn't matter will this be your custom solution for getting updated entity or build in one, these functions are stil just duplicate one another.

    How can you fix that?

    Option 1:

    From my experince there it's quite rare case to have functions like that, which update only one property of the entity, so I have just one function that takes the whole new entity with all the updated fields:

    save(entityId, newEntityValue: EntityType) { 
      http.post('/url', newEntityValue).subscribe((responseValue) => { 
        store.update(entityId, newEntityValue) // or "responseValue"
      }) 
    }
    

    Option 2:

    In case you wanna stick to updating seprarte properties, you can write one reusable function for that:

    updateEntity(entityId, partialValue: Partial<EntityType>) {
      const newValue = merge(store.getEntity(entityId), partialValue);
      http.post('/url', newValue)).subscribe((responseValue) => { 
        store.update(entityId, newValue) // or "responseValue"
      }) 
    }
    

    Where merge is some function for deep objects merging, like the one lodash has.

    This solution is only one function that allow updating any property or even multiple of them;