Skip to content
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

Svelte 5: Placeholder in select not displayed #12152

Closed
shinokada opened this issue Jun 23, 2024 · 6 comments · Fixed by #12181
Closed

Svelte 5: Placeholder in select not displayed #12152

shinokada opened this issue Jun 23, 2024 · 6 comments · Fixed by #12181
Assignees
Milestone

Comments

@shinokada
Copy link

shinokada commented Jun 23, 2024

Describe the bug

demo

image

As you can see in the above image, a placeholder, "--Please choose an option--" is not displayed when I use a component.

Both selects are identical but using component doesn't show the placeholder.

Select.svelte

<select name="pets" id="pet-select1" {...$$restProps}>
<slot></slot>
</select>

App.svelte

<script>
	import Select from './Select.svelte'
</script>
<div>
<label for="pet-select">Choose a pet 1:</label>

<Select>
	<option value="">--Please choose an option--</option>
  <option value="dog">Dog</option>
  <option value="cat">Cat</option>
</Select>
</div>

<div>
<label for="pet-select">Choose a pet 2:</label>

<select name="pets" id="pet-select2">
  <option value="">--Please choose an option--</option>
  <option value="dog">Dog</option>
	<option value="cat">Cat</option>
</select>
</div>

Reproduction

demo

Logs

No response

System Info

System:
    OS: macOS 14.6
    CPU: (10) arm64 Apple M2 Pro
    Memory: 79.55 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.14.0 - ~/.nvm/versions/node/v20.14.0/bin/node
    npm: 10.7.0 - ~/.nvm/versions/node/v20.14.0/bin/npm
    pnpm: 9.4.0 - /opt/homebrew/bin/pnpm
    bun: 1.1.8 - ~/.bun/bin/bun
  Browsers:
    Chrome: 126.0.6478.115
    Edge: 126.0.2592.68
    Safari: 17.6
  npmPackages:
    svelte: 5.0.0-next.164 => 5.0.0-next.164

Severity

annoyance

@brunnerh
Copy link
Member

brunnerh commented Jun 23, 2024

Apparently something in the {...$$restProps} logic causes the issue, i.e. without it the option will be selected.

No rest props to rest props diff
 import * as $ from "svelte/internal/client";

-var root = $.template(`<select name="pets" id="pet-select1"><!></select>`);
+var root = $.template(`<select><!></select>`);

 export default function Select($$anchor, $$props) {
+       const $$sanitized_props = $.legacy_rest_props($$props, [
+               "children",
+               "$$slots",
+               "$$events",
+               "$$legacy"
+       ]);
+
+       const $$restProps = $.legacy_rest_props($$sanitized_props, []);
        var select = root();
+       let attributes;
+
+       $.init_select(select, () => attributes.value);
+
        var node = $.child(select);

        $.slot(node, $.default_slot($$props), {}, null);
+
+       $.template_effect(() => {
+               attributes = $.set_attributes(
+                       select,
+                       attributes,
+                       {
+                               name: "pets",
+                               id: "pet-select1",
+                               ...$$restProps
+                       },
+                       true,
+                       ""
+               );
+
+               if ("value" in attributes) {
+                       $.select_option(select, attributes.value);
+               }
+       });
+
        $.append($$anchor, select);
 }

Migrating the code to the runes equivalent does not affect the result.


Explicit declaration and setting of value to '' by default would be a workaround:

<script>
	export let value = '';
</script>
<select name="pets" id="pet-select1" {value} {...$$restProps}>

REPL

@Neptunium1129
Copy link

Neptunium1129 commented Jun 24, 2024

use chidren and props

REPL

@trueadm trueadm self-assigned this Jun 24, 2024
@trueadm trueadm added this to the 5.0 milestone Jun 24, 2024
@jrmoynihan
Copy link

jrmoynihan commented Jun 25, 2024

^ correct solution above. Svelte 5 == children snippets instead of slots.

They're also not placeholders. Those are actual options in the <select> with a value of an empty string and can set the value of the select element (or component, in your case), unlike the placeholder attribute on input elements, which never get bound to the value of the input.

@brunnerh
Copy link
Member

Whether it's legacy or runes does not matter, it's broken either way.
The code given in @Neptunium1129 REPL is wrong, it sets a non-existent property called rest instead of spreading it.

REPL with spread

@shinokada
Copy link
Author

For a legacy project, I can't use children and $props().
As you can see in my demo, it is not a runes project.

@trueadm
Copy link
Contributor

trueadm commented Jun 25, 2024

Ah, this seems to be an issue with the internal init_select logic. Digging into it now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants