79488313

Date: 2025-03-06 05:07:19
Score: 0.5
Natty:
Report link

You can achieve something like this with a signalStoreFeature. Like this article, "Extending the NgRx signal store with a custom feature"

A summary of the article:

The end product is adding this one line to your stores:

withCrudOperations<MyDto>(MyService),

MyService implements an interface like this:

export interface CrudService<T> {
  fetch(id: string): Observable<T>;
  update(value: T): Observable<T>;
  //... other ones
}

The signature of the signalStoreFeature, and an example of a method in use:

export type BaseEntity = { id: string };

export type BaseState<Entity> = {
  items: Entity[];
};

export function withCrudOperations<Entity extends BaseEntity>(
  dataServiceType: Type<CrudService<Entity>>
) {
  return signalStoreFeature(
    {
      state: type<BaseState<Entity>>(),
    },
    withMethods((store) => {
      const service = inject(dataServiceType);

      return {
        update: rxMethod<Entity>(
            // details in article
        ),
        // ... the rest of the methods
      }
    }
  )
}

For a more powerful entity based approach, there is withDataService from the ngrx-toolkit. It is based around withEntities and can add the collection name to the respective state/methods. However, it uses promises instead of observables. I had a PR to extend it to support observables that you could pull pieces from as needed.

Between the article's basics about a signalStoreFeature that is observable CRUD based and withDataService's advanced source code, you could piece together something really nice. That's what I did.

Reasons:
  • Blacklisted phrase (1): this article
  • Long answer (-1):
  • Has code block (-0.5):
  • Low reputation (1):
Posted by: Michael Small