-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Allow specifying non-special bindings as readonly #7712
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
Comments
I also want this feature in Svelte. Additionally, there are some generic readonly "props" in Svelte component - those are the slot props. <Component bind:let:p={var} /> I know that the code isn't the cleanest, but it is just an association. |
Why is just passing props not enough? Foo.svelte <script>
import { onMount } from "svelte";
export let foo = 0;
onMount(() => {
const t = setTimeout(() => {
foo++;
}, 100);
return () => {
clearTimeout(t);
};
});
</script>
Foo at Foo.svelte: {foo} App.svelte <script>
import Foo from "./Foo.svelte";
let foo;
</script>
<Foo foo="{foo}" />
<h1>{foo}</h1>
Foo at App.svelte: {foo} |
This issue is about the opposite, exporting a value from |
Ah got it. Thank you for your explanation! My first impression is that the complexity of the bindings will make them more difficult to understand.
Also, at least in my experience, it seems that the timing of passing a child component's value to a parent component is often controlled by the code, rather than when the value is changed. (e.g. passing value to the parent when a button is clicked) Thought? |
Quite simply, look at the special cases svelte has for If you don't see the need for this then I would argue the special case should also be removed from the builtin elements. If it can't be removed from the builtin elements then clearly this behaviour is desirable and necessary and we should make it available everywhere. The issue with timing is actually most of the reason for this request. If you do this with a normal two-way binding then the parent is in charge, which means the initial value comes from the parent, and the only way to get the value from the child is to have the child do something like |
Hi, Nice feature to have, but but I think the I think it would be clearer to use a specific JS label to declare read-only variables :
|
I'm new to Svelte, and was shocked that this isn't already present. Readable stores seems like a way to work around this limitation. For e.g.:
Seems inferior to first class read-only properties though. UPDATE: this doesn't work, though I'm not sure why. On the consuming end of the component the store values just come out undefined. e.g. {dataset.$busyState} is always undefined |
Would it be more straight forward to have it be a modifier on the property itself? This way the reader immediately knows without looking elsewhere. Something like this:
|
@n8allan as far as i know, svelte JS syntax has to be somewhat ESM compatible, |
We can always have a JSDoc-style comment, though I agree with your suggestion as well. You suggestion is actually good as we can have that these props will always be reactive🙂 |
This might be a possible workaround using a store:
The writable store value could be changed at any point within the child component so better than using a readable store only.
If the parent attempts to change the value of store, svelte generates this error message: Here is a code example: |
This feature can be easily implemented: <script>
export let value = "foo"
let _value;
// if you want to set init value from outside
// uncomment this line:
// _value = value;
$: value = _value;
</script>
<input bind:value={_value} /> Outside component bind to So I don’t think this feature needs language level support. I’d suggest a "won’t do" label for this one. |
Oh that is interesting and useful. Expanding your example a bit, I found a way to make it throw if you try to modify it from outside:
So it is doable, but it is very clumsy without language support. |
@SystemParadox My impl requires only two extra lines, I think it's pretty far away from clumsy, and to me that already covers all of this feature request. Enlighten me if I missed out something. I cannot possibly imagine that, if Svelte were to provide language support, it'd implement it the way you describe: to THROW AN ERROR when outside set to readonly prop??? I mean, who want that? Some strange use cases maybe, but definitely not the majority and not the way this feature would be handled. |
@hackape Very nice solution with the reactive shadow variable. With your solution, I suppose the parent code would use the same syntax as a 2-way bind @SystemParadox hacked in a runtime feedback for the dev, which I certainly wouldn't want to have in my code, hence the request for language support... |
I noticed an earlier remark by @SystemParadox:
Just wanna clarify, this is inacurate. If parent value is |
@kenbankspeng Yeah if what's important is the "readonly" semantic, it can only be done with language support. Still I don't believe this feature deserves a dedicated language element, for following reasons:
|
I’ve switched from the shadow variable to a dispatcher event.
…On Wed, Jul 26, 2023 at 8:19 AM hackape ***@***.***> wrote:
@kenbankspeng <https://github.com/kenbankspeng> Yeah if what's important
is the "readonly" semantic, it can only be done with language support.
Still I don't believe this feature deserves a dedicated language element,
for following reasons:
1. Things like <div bind:clientWidth> as readonly binding is
well-known, and is a feature much loved. The fact that "readonly binding
exists on some special elements without any clue other than mentioned in
the docs" should not surprise any half-serious svelte users.
2. You can always (and probably should) use custom event to express
the "readonly semantic" on component API level, because it really is an
*event*. So there's already an escape hatch. And if you don't care
about semantic and only want the readonly runtime behavior, then you can
use my workaround
<#7712 (comment)>
.
3. Simplicity is king. This is the biggest reason why I don't like
this proposal. Any new language feature also adds cognitive burden to
language user. Before you know, Svelte could also grows into sth with a
bunch of features that ppl hate, like every other practical prog-langs. 2nd
law of thermodynamics will always find its way, but we can at least try
resist it a bit longer.
—
Reply to this email directly, view it on GitHub
<#7712 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AGNINCD2AYD6H6OSZS6ICLTXSEDNBANCNFSM54L2DHHQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Pretty sure this can be closed due to the new |
But the function bindings syntax is only applicable for the consumer of the binding, right? What I'm looking for is a way to define it on the component side as a readonly binding. |
Isn't that just a prop? |
As mentionend in this thread, there are already readonly bindings in Svelte like dimension bindings: I would appreciate it if I could define my own bindings and declare them as readonly in the Component I'm defining. Just as an example I might have a let headerHeight = $state(0);
...
<Header bind:height={headerHeight} /> In this case it would never make sense for the wrapper to manually modify the headerHeight = 42; // should throw an error: "headerHeight is readonly" To me, this is a lot more concise than setting up a #7712 (comment) mentions that it would "add cognitive burden" but I would argue that language level support for readonly bindings would actually lessen the cognitive burden by preventing the consumer of a component (that might come from a third-party module) from accidentaly assigning to a binding value that is ment as a readonly binding. |
Maybe svelte 5.9.0 Function bindings help with this? |
Describe the problem
Currently there appears to be no way to define a components binding as readonly, this is supported on special inbuilt elements, such as
input
,video
andaudio
(for example, for "read_only_media_attributes") but Svelte currently lacks support for specifying anything outside of inbuilt elements as a readonly binding.Looking through the source, it looks like the binding type is decided around here, and is conditioned based on the type of element:
https://github.com/sveltejs/svelte/blob/master/src/compiler/compile/nodes/Binding.ts#L88
Sorry if this has already been discussed but I couldn't find an existing issue covering this topic.
Describe the proposed solution
We should have some way of specifying a readonly binding, for example, by using the reserved
export let $variable
syntax:Foo.svelte:
App.svelte
I'm not aware of if this syntax is intended for something else, someone might be able to chime in and suggest something that might be better suited and fit in better with the general design of Svelte.
Alternatives considered
We'd like this to warn developers not to write to certain values to components as they won't affect anything, since the component that's providing those bindings is doing some side effect that isn't controllable from the parent component.
If they do, it doesn't directly affect any result (nothing happens), so our alternative solution is just to mark these bindings as readonly in our JSDoc.
Importance
nice to have
The text was updated successfully, but these errors were encountered: