-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Description
Describe the problem
Like class names, IDs are global in vanilla HTML, which is fundamentally at odds with a component-based way of writing code. Compliant HTML code with labels, for example, is supposed to use matching ids on the for= attribute of the label and the id= attribute of the input.
Ideally, one could write a labelled input component like this in svelte:
<div>
<label for="text-input"><slot/></label>
<input id="text-input">
</div>
Unfortunately, if you use more than one instance of this component, it will break, so svelte-users have to roll-their-own ID generating solution to insure IDs do not conflict.
Currently, I believe the recommended solution is something like this:
<script context="module">
let counter = 0
</script>
<script>
counter += 1;
let id = 'text-input-'+counter
</script>
<div>
<label for={id}><slot/></label>
<input id={id}>
</div>
That's a lot of boilerplate just to create a label and an input, and it's still fragile code since there remains the potential for id-collision with other components. What's more, it requires using a module-level script, which is a somewhat advanced feature of svelte, to accomplish a simple task required in just about any forms-based app.
Describe the proposed solution
Ideally, id= and for= attributes would work in a scoped way out of the box, just as classes do.
<div>
<label for="text-input"><slot/></label>
<input id="text-input">
</div>
Would generate code with hashed prefixes added to id= and for= attributes automatically.
<!-- output -->
<div>
<label for="svelte-e9wl34-text-input"><slot/></label>
<input id="svelte-e9wl34-text-input">
</div>
That would then require syntax to allow global values to be used when wanted, like so:
<div>
<label for|global="text-input"><slot/></label>
<input id|global="text-input">
</div>
Generates code without hashed prefixes added.
<!-- output -->
<div>
<label for="text-input"><slot/></label>
<input id="text-input">
</div>
Alternatives considered
Require special syntax to use scoped IDs
The above solution would be a breaking change. To avoid a breaking change, we could instead introduce a syntax for specifying local IDs. This would leave all existing code alone, but would mean that working with ids and classes would feel different.
<div>
<label for|local="text-input"><slot/></label>
<input id|local="text-input">
</div>
Provide some utility functions for generating IDs on the fly securely
<script>
import {generateId} from 'svelte/future-magic';
</script>
<div>
<label for={generateId("text-input")}><slot/></label>
<input id={generateId("text-input")}>
</div>
This one is easy to do project-by-project if need be, so it would just be a convenience to add it to svelte. It doesn't feel nearly as elegant as building it into the syntax. That said, it would still be nice to standardize a way to do this and to implement it in a way that would prevent collisions between component libraries in the future.
Importance
nice to have