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

Unable to populate <select> default value to object during initial load #8238

Closed
wngasinur opened this issue Jan 31, 2023 · 10 comments
Closed

Comments

@wngasinur
Copy link

wngasinur commented Jan 31, 2023

I've select input bind to object, but I'm unable to populate the selected value when the screen is loaded for the first time.

<script>
	let questions = [
		{ id: 1, text: `Where did you go to school?` },
		{ id: 2, text: `What is your mother's name?` },
		{ id: 3, text: `What is another personal fact that an attacker could easily find with Google?` }
	];
         // populate initial/default of select
	let selected = { id: 1, text: `Where did you go to school?` };


</script>

<h2>Insecurity questions</h2>

<form>
	<select value={selected} >
		{#each questions as question}
			<option value={question}>
				{question.text}
			</option>
		{/each}
	</select>

</form>

Current behavior: the select is populated as empty
Expected behavior: the select should be populated with selected value/text

Reproduction

n/a

Logs

No response

System Info

n/a

Severity

annoyance

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Jan 31, 2023

These are different objects, fix:

let selected = questions[0];

alternatively use ids for value everywhere. It's more flexible in my opinion (e.g. saving the last selected object for the future works because the id is primitive)

@coryvirok
Copy link
Contributor

Looks like the same issue as #8240. I.e. your code works the way you expect if you use svelte version 3.35.0.

@wngasinur
Copy link
Author

wngasinur commented Feb 1, 2023

These are different objects, fix:

let selected = questions[0];

alternatively use ids for value everywhere. It's more flexible in my opinion (e.g. saving the last selected object for the future works because the id is primitive)

We need to get and save the whole object, not just a plain id.
In our use case, the form data and lookup are coming from different sources.
i.e :
surveyData = tableQuery()
// return selected questions JSON

lookupData = differentTableQuery()
// return questions JSON

it's so much hassle if we need to additional logic just to remap to the right value on client side.

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Feb 1, 2023

it's so much hassle if we need to additional logic just to remap to the right value on client side.

Where hassle? https://svelte.dev/repl/80081a1cbd8242d39249f3dafbd8b041?version=3.55.1

@Prinzhorn
Copy link
Contributor

Looks like the same issue as #8240. I.e. your code works the way you expect if you use svelte version 3.35.0.

This is entirely different. It just looks like it's working, because the selected item happens to be the first one. Set it to anything else and the first one is still selected.

@wngasinur
Copy link
Author

wngasinur commented Feb 1, 2023

@Prinzhorn
I think there's misunderstanding about the issue, let me re-share again the code here (apologize for some reason i can't write to REPL)

<script>
	let questions = [
		{ id: 1, text: `Where did you go to school?` },
		{ id: 2, text: `What is your mother's name?` },
		{ id: 3, text: `What is another personal fact that an attacker could easily find with Google?` }
	];
         // populate initial/default of select
	let selected = { id: 1, text: `Where did you go to school?` };


</script>

<h2>Insecurity questions</h2>

<form>
	<select value={selected} >
		{#each questions as question}
			<option value={question}>
				{question.text}
			</option>
		{/each}
	</select>

</form>

I need the 'selected' to bind to object not just a plain string/number, like what you share.
This work perfectly fine whenever I change the select option, it does the binding properly.

But the issue comes, when I need this select to be populated with initial value which is a object, it's showing as empty.

@Prinzhorn
Copy link
Contributor

Prinzhorn commented Feb 1, 2023

I understand that you want that, but Svelte can't deep compare the object to make that magically work. Even if it would, then this will break if your two sources of truth change (e.g. you change the question text slightly in the questions DB, but not in the "selected" DB). If you want to keep using objects, you must go through some hassle. Depending on how exactly your code works you can potentially easily abstract this to find the appropriate matching object.

https://svelte.dev/repl/59f17560a366484289a4b51c53919b12?version=3.55.1

@wngasinur
Copy link
Author

wngasinur commented Feb 1, 2023

If there's change two sources, then it should show as empty (nothing selected).
It's just weird that for <select>, we can do two-way binding with bind:value to object, but unable to set initial value for bind:value to object.

Would be great if svelte implement the default object equality, e.g: comparing all attributes, and allow user to extend them as needed

@stackasaur
Copy link

stackasaur commented Feb 1, 2023

@wngasinur,
If all you're trying to do is prepopulate the select with one of the options, you could just set selected to one of the options in the list:

let selected = questions[0];

That way, you're comparing the same object.

@wngasinur
Copy link
Author

ok, closing the issue, as it seems the best way to handle this is to use

let selected = questions[0];

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

No branches or pull requests

4 participants