-
-
Notifications
You must be signed in to change notification settings - Fork 4.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
[feat] Props data checker/converter #13124
Comments
You can use an object with a getter/setter to achieve this: <script>
let { value = $bindable() } = $props();
let proxied = {
get value() { return new Date(Date.parse(d)) },
set value(v) { value = v.toISOString() }
}
</script>
<... bind:value={proxied.value} /> |
This solution is great from the caller perspective (typically to pass to a bind:value). But if I use the I will try to use this with a $derived... |
I didn't succeed with getter/setter with a reactive value (it update the value too frequently). So I use two $effect.pre() : let {
date : dateAsString = $bindable()
} = $props();
let date = $state();
let date_value;
$effect.pre( () => {
// when dateAsString change, update the date :
if (date_value !== dateAsString) {
date = new SvelteDate(dateAsString);
}
});
$effect.pre(() => {
// when date change, update the dateAsString
date_value = date.toISOString().substring(0,10);
if (date_value !== untrack(()=>dateAsString)) {
dateAsString = date_value;
}
}); See here : REPL It's work, but it's a bit verbose... I can make it an external function, but then I have to pass the getter/setter for the state and the prop : let date = $state();
pipe(
// get_state
() => date,
// set_state
(new_state) => date = new_state,
// get_prop
() => dateAsString,
// set_prop
(new_prop) => dateAsString = new_prop,
// prop_to_state
(prop) => new SvelteDate(prop),
// state_to_prop
(state) => state.toISOString().substring(0,10)
); Link : REPL |
Rather than passing around Alternatively, if you're transforming data, then use |
Then add one extra line let { value = $bindable() } = $props();
const getter = $derived(new Date(Date.parse(d)));
let proxied = {
get value() { return getter},
set value(v) { value = v.toISOString() }
} |
@trueadm : yes but I don't want to pass a class instance. I just want a simple string. A real-life example would be a DateInput component. <script>
let date = $state("2024-09-10");
</script>
<DateInput bind:value={date} /> The component should be called with a string representing the date, but inside my component I want to use a SvelteDate (or another date-library) to handle correctly the calendar. I want to use this component like an Exemple here : REPL Currently, I have to use $effect for that... |
You don't need effects, you can just use objects like mentioned above – or create your own proxied object. However, given you want a |
Describe the problem
Sometimes it can be useful to validate or convert the value of a prop before using it.
Some examples :
And of course I would like to keep this responsive and recheck the prop every time it is changed from outside
Currently I see two way to do this.
This is fine, even if it involves duplicating the props.
This solution is more verbose, and the effect is re-executed even when I change the value inside my component (useless).
Describe the proposed solution
I think it would be nice to have a way to replace the prop's default value with a custom function.
Something like this (using a $pipe rune for the exemple - but the name should be reviewed) :
The $pipe() rune requires a function as a parameter, which will be used to convert the value of the prop.
There is no default value, it is up to the function to handle the undefined case...
Of course, we should have the same with $bindable(), something like this :
$bindable.pipe() should accept a second function, allowing the reverse conversion to be done when the value is passed back to the caller
Caveat :
I don't known how to handle this with TypeScript, as the prop should have two distinct type.
From the caller perspective it should be a string, but in the component it should be a Date
It would be nice to have a simple way to declare this, like something like that :
But I don't know if it's easily achievable...
Importance
nice to have
The text was updated successfully, but these errors were encountered: