Skip to content

Expose selectId As a Prop When Using withEntities #4728

@JordanW9232

Description

@JordanW9232

Which @ngrx/* package(s) are relevant/related to the feature request?

signals

Information

When calling withEntities with a config like this:

withEntities(entityConfig({
  entity: type<ExampleEntity>(),
  selectId: entity => entity.customId
})),

I would like the selectId function to be populated in the props of the store so I can reference it later. Maybe call it entitySelectId in the EntityProps<Entity> type. That way when using one of the entity updaters I could just call it like this:

patchState(store, setAllEntities(entities, { selectId: store.entitySelectId });

If using a named entity store, then it might look like this:

withEntities(entityConfig({
  entity: type<ExampleEntity>(),
  selectId: entity => entity.customId,
  collection: 'custom'
})),

The entitySelectId would then be prepended with the collection specified. Like customEntitySelectId. Then we could use it like this:

patchState(store, setAllEntities(entities, { selectId: store.customEntitySelectId, collection: 'custom' });

Describe any alternatives/workarounds you're currently using

In more simple scenarios this isn't really a problem since you can just do this:

const config = entityConfig({
  entity: type<ExampleEntity>(),
  selectId: entity => entity.customId
});

const MyStore = signalStore(
  withEntities(config),
  withMethods(store => ({
    update(entities: ExampleEntity[]) {
      patchState(store, setAllEntities(entities, { selectId: config.selectId });
    }
  }))
);

But in a more complex scenario when you have a custom store feature that expects withEntities to already have been called, you basically need your feature to specify the selectId again:

function withMyCustomEntities<Entity>(customSelectId: SelectEntityId<NoInfer<Entity>>)
{
  return signalStoreFeature(
    {
      state: type<EntityState<Entity>>(),
      props: type<EntityProps<Entity>>()
    },
    withMethods(store => ({
      update(entities: Entity[]) {
        patchState(store, setAllEntities(entities, { selectId: customSelectId }));
      }
    }))
  );
}

Which you would use like this:

const config = entityConfig({
  entity: type<ExampleEntity>(),
  selectId: entity => entity.customId
});

const MyStore = signalStore(
  withEntities(config),
  withMyCustomEntities(config.selectId)
);

But if it was just attached to the store I wouldn't need the extra parameter in my custom feature. I could just do this:

function withMyCustomEntities<Entity>()
{
  return signalStoreFeature(
    {
      state: type<EntityState<Entity>>(),
      props: type<EntityProps<Entity>>()
    },
    withMethods(store => ({
      update(entities: Entity[]) {
        patchState(store, setAllEntities(entities, { selectId: store.entitySelectId }));
      }
    }))
  );
}

I would be willing to submit a PR to fix this issue

  • Yes
  • No

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions