2

What is the correct way to bind a select element to an object (rather than a string value) but still have the HTML element submit a string value?

I've managed to get this working, but it almost seems like I'm exploiting a bug:

<select v-model="selected" v-on:change="price=selected.price">
    <option v-for="item in items" v-bind:value="item" value="{{ item.id }}">{{ item.name }}</option>
</select>

This works as intended: the "selected" property is attached to the "item" object, but the form POSTs just the item's ID. However, if I reverse the order of the HTML attributes, so that value={{ item.id }} comes before v-bind:value="item", then the form POSTs "[Object]" rather than, e.g., "3".

The fact that it's so fragile makes me think I'm doing something wrong.

So what's the right way to handle this?

3 Answers 3

1

I had a similar situation in which I built several vue components that could be used both within a vue component or within a standard form.

<select v-model="selected" v-on:change="price=selected.price">
    <option v-for="item in items" :value="JSON.stringify(item)">{{ item.name }}</option>
</select>

Appears to be what you are after. I also had success using a computed property or filter but I decided that stringify was most readable.

Sign up to request clarification or add additional context in comments.

Comments

1

I fixed it by using this approach:

<select v-model="product">
  <option v-for="obj in choices" :value="obj">{{ obj.name }}</option>
</select>
<input type="hidden" name="product" :value="choice.id">

In summary: don't give your select a name but give that name to your hidden input and provide the ID as value on that element instead.

1 Comment

For some reason I overlooked this comment and ended up doing this exact thing. This works as well!
0

I see in both the cases, HTML being rendered as following:

<select>
  <option value="[object Object]">name1</option>
  <option value="[object Object]">name2</option>
  <option value="[object Object]">name3</option>
  <option value="[object Object]">name4</option>
</select>

Case 1 : v-bind:value="item" value="{{ item.id }}" : fiddle

Case 2 : value="{{ item.id }}" v-bind:value="item" : fiddle

So both the cases are equivalent as far as HTML being rendered. Ideal way to do it without confusion will be just using v-bind:value="item" like following:

<select v-model="selected" v-on:change="price=selected.price">
    <option v-for="item in items" v-bind:value="item">{{ item.name }}</option>
</select>

You should v-bind to item or item.id depending on what you want to assign to selected variable.

8 Comments

Thanks, but neither of those works. If I v-bind to item then the value submitted by the form is the string "[object Object]". If I v-bind to item.id, then that problem is fixed, but the selected model is just the id, not the whole item, which I need it to be.
Why do you want to have selected to be whole model: selected will be whatever you use v-bind in <option>. I see selected as whole item in http://jsfiddle.net/sh9kd1gg/2/.
I need selected to be the whole model because I need to reference the "price" property of the model (item.price). In the fiddle you posted, that works (more or less) but then we're back to the original problem. When that form is posted, the value of that select field will be "[object Object]". I need it to be the item.id.
@adamthehutt check this fiddle: jsfiddle.net/sh9kd1gg/3, If this not works, Can you update this fiddle with your issue.
Yes, that works, but it requires that you intercept the form submission in javascript (to capture selected.id and overwrite the value of that form field). I was hoping to be able to do a normal HTML form submission. But I guess that's not possible. Thanks anyway for your help.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.