Best practice for extending withEntities with more reuseable array features (e.g. building a generic filter feature?) #4767
Replies: 2 comments 3 replies
-
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.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
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