Best practice for extending withEntities with more reuseable array features (e.g. building a generic filter feature?) #4767
Replies: 2 comments 1 reply
-
If I would write an extension, then the extension would also call I hope that I didn't miss it, but in your example I didn't see a single one where you called |
Beta Was this translation helpful? Give feedback.
-
So this is my best result until now.
What do you think @rainerhahnekamp ? I was not able to make it work for
Is it save to "overwrite" the computed entities signal like this? What I like about this approach is, that the store consuming ui-components would not even notify that a filter was plugged out or in (at least if I refactor the updateFilterString method to its own feature store). export type FilterState = {
filterString: string | undefined;
};
export const initialFilterState: FilterState = {
filterString: undefined,
};
export function withFilterByString<
T extends Record<string, any>,
K extends keyof T & string
>(filterKeys: K[]) {
return signalStoreFeature(
{
state: type<{ entityMap: EntityMap<T> }>(),
},
withState<FilterState>(initialFilterState),
withComputed((store) => ({
entities: computed(() => {
const entityMap = store.entityMap();
const entities = Object.values(entityMap);
const filterString = store.filterString();
if (!entities || entities.length === 0 || !filterString) {
return entities;
}
return entities.filter((entity) => {
const searchableTextFields = filterKeys
.map((key) => String(entity[key]))
.join(' ')
.toLowerCase();
const filterResults = searchableTextFields.includes(
filterString.toLowerCase()
);
console.log(filterResults);
return filterResults;
});
}),
})),
withMethods((store) => ({
updateFilterString(filterString: string) {
patchState(store, { filterString: filterString });
console.log(store.filterString());
},
clearFilter() {
patchState(store, { filterString: undefined });
},
}))
);
} Then I can use it flexible and can even chain it with other featureFilters which overwrite entities. The filter keys are fully typed. export const ProfileFollowerStore = signalStore(
{
providedIn: 'root',
},
withLoadingStore(),
withAlertStore(),
withEntities<Follower>(),
withFilterByString<Follower, 'first_name' | 'last_name'>([
'first_name',
'last_name',
]),
withMethods(
// ...
)
) |
Beta Was this translation helpful? Give feedback.
-
Does a best practice exist how to extend the withEntities store?
I would like to build a generic feature/custom feature/withFeature which I can use to filter the entites stored in a named withEntities store.
The requirements would be similiar to:
I am not sure if extension is the correct phrase. Probably it is more an extension. In a best case scenario, I would wish that, the consuming store would look like this:
Since I believe processing entities is a common use case, I wanted to ask if someone can provide a related example, a guide, documentation or code snippet?
My approach so far is (and I think it works for EntityStores)
Use entittyMap in the featureStore():
But if I want to use a named store, it does not work anymore. Are the named signals state properties or computed?
I think it would be helpful for most developers to extend the input docs with a section how to access withEntity properties (e.g. use them as input in feature stores) or extend the entity docs with a guide how to extend named entities. I think it would be good to add more documentation about the difference between maps and computed signals (thats a big difference here, isn't it?) in this context.
Beta Was this translation helpful? Give feedback.
All reactions