-
-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose more models to the public API: SignalStoreFeatureResult and InputSignalStore<Input> #4272
Comments
Hi @GuillaumeNury, I agree that we need more types in the public API to support advanced use cases such as this one. However, it's important to mention that this is not the right way of building custom features. We should not reimplement the logic of base features, but use them instead because the internal logic can change in the meantime. This is how type TabVisibilityMethod<Input extends SignalStoreFeatureResult> = (
store: Prettify<
StateSignals<Input['state']> &
Input['computed'] &
Input['methods'] &
StateSource<Input['state']>
>
) => void;
export function withTabVisibility<
Input extends SignalStoreFeatureResult
>(methods: {
onTabVisible?: TabVisibilityMethod<Input>;
onTabHidden?: TabVisibilityMethod<Input>;
}): SignalStoreFeature<Input, { state: {}; computed: {}; methods: {} }> {
return signalStoreFeature(
type<Input>(),
withHooks((store) => {
const visibilityChangeFn = () => {
document.hidden
? methods.onTabHidden?.(store)
: methods.onTabVisible?.(store);
};
return {
onInit() {
document.addEventListener('visibilitychange', visibilityChangeFn);
},
onDestroy() {
document.removeEventListener('visibilitychange', visibilityChangeFn);
},
};
})
);
}
// Usage:
const CounterStore = signalStore(
withState({ count: 0 }),
withMethods((store) => ({
increment(): void {
patchState(store, { count: store.count() + 1 });
},
decrement(): void {
patchState(store, { count: store.count() - 1 });
},
})),
withTabVisibility({
onTabVisible: ({ increment }) => increment(),
onTabHidden: ({ decrement }) => decrement(),
})
); The following models are missing from the public API to implement features such as this one:
They will be added to the public API. |
@markostanimirovic thanks for your reply! I cannot find what Would it be better to expose // This type avoid exposing "utils" like Prettify
export type SignalStoreFeatureInputStore<Input extends SignalStoreFeatureResult> = Prettify<
StateSignals<Input['state']> &
Input['computed'] &
Input['methods'] &
StateSource<Input['state']>
> The previous implementation would become: type TabVisibilityMethod<Input extends SignalStoreFeatureResult> = (
store: SignalStoreFeatureInputStore<Input>
) => void;
export function withTabVisibility<
Input extends SignalStoreFeatureResult
>(methods: {
onTabVisible?: TabVisibilityMethod<Input>;
onTabHidden?: TabVisibilityMethod<Input>;
}): SignalStoreFeature<Input, { state: {}; computed: {}; methods: {} }> {
return signalStoreFeature(
type<Input>(),
withHooks((store) => {
const visibilityChangeFn = () => {
document.hidden
? methods.onTabHidden?.(store)
: methods.onTabVisible?.(store);
};
return {
onInit() {
document.addEventListener('visibilitychange', visibilityChangeFn);
},
onDestroy() {
document.removeEventListener('visibilitychange', visibilityChangeFn);
},
};
})
);
}
// Usage:
const CounterStore = signalStore(
withState({ count: 0 }),
withMethods((store) => ({
increment(): void {
patchState(store, { count: store.count() + 1 });
},
decrement(): void {
patchState(store, { count: store.count() - 1 });
},
})),
withTabVisibility({
onTabVisible: ({ increment }) => increment(),
onTabHidden: ({ decrement }) => decrement(),
})
); Anyway, thanks for the |
It will be useful for features that need access to all store members. However, there may be a case where you want to restrict access and expose e.g. only state and computed signals: type MyCustomFeatureMethod<Input extends SignalStoreFeatureResult> = (
store: Prettify<StateSignals<Input['state']> & Input['computed']>
) => void; Therefore, types are separated for better flexibility. |
@markostanimirovic Ok, makes sense! |
@markostanimirovic |
Which @ngrx/* package(s) are relevant/related to the feature request?
signals
Information
In order to add more complexe features, it would be great to expose more models to the public API.
Here is an example of what I try to achieve
It is possible but I used many unexposed models:
What would be marvelous would be to:
EmptyFeatureResult
andSignalStoreFeatureResult
SignalStoreFeatureInputStore<Input>
(could be used bywithMethods
andwithHooks
)createFeatureInputStore
(could be used bywithMethods
andwithHooks
as well)I could have written:
Thanks for this awesome lib ❤️
Describe any alternatives/workarounds you're currently using
It is possible to add hooks with:
Then:
The
onTabVisible
method seems completely decoupled from thewithTabVisibility
feature.I would be willing to submit a PR to fix this issue
The text was updated successfully, but these errors were encountered: