1

I've got a form with about 10 select elements built from an array in my Vue data.

The array of selectors is empty initially and then an AJAX call populates the array and Vue builds the HTML - I've kept the snippet below simplified just to demonstrate the issue I'm having with v-model

I want to create an object that has all the selected values in it, so I'm trying to use v-model="selected[ selector.name ]" as per the example below. I want to easily be able to ask for selected.make or selected.fuel

Now this works if I initialize the selected property like this:

selected: { make: 'audi', fuel: 'petrol' }

If I leave it blank, like in the example, {}, then it doesn't get updated. I don't want to manually hardcode all the properties of selected, I only want to be listing them once in the server side code that gets sent via AJAX

So am I missing something completely obvious, should I be doing this in a different way?

Maybe a method to find the dropdown that matches a field name and returns the value? Just that doesn't seem like a very Vue thing to do.

var app = new Vue({
 el: '#example',
 data: {
  selectors: [
   {
    name: 'make',
    options: ['audi','bmw']
   },
   {
    name: 'fuel',
    options: ['petrol','diesel']
   }
  ],
  selected: {}
 }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>

<div id="example">

<template v-for="selector in selectors">
  <select v-model="selected[ selector.name ]">
    <option v-for="option in selector.options">{{option}}</option>
  </select>
</template>
  
<p>
  {{selected.make}}
  <br />
  {{selected.fuel}}
</p>
  
</div>
chrisandrew.cl
  • 867
  • 14
  • 30
Pete
  • 4,542
  • 9
  • 43
  • 76

1 Answers1

5

it's probably becuase you're not setting new keys on an object with this.$set

try:

this.$set(this.selected, 'make', 'audi')

Not using this.$set - alias of Vue.set - will mean Vue doesn't set the new key as reactive, and in turn won't be watching for any updates to it, docs: https://v2.vuejs.org/v2/api/#vm-set

var app = new Vue({
    el: '#example',
    data: {
        selectors: [{
            name: 'make',
            options: ['audi', 'bmw']
        }, {
            name: 'fuel',
            options: ['petrol', 'diesel']
        }],
        selected: null,
    },
    created () {
        // this would happen following your ajax request - but as an example this should suffice
        this.selected = {}
        this.selectors
            .forEach((selector) => {

                this.$set(this.selected, selector.name, '')

            })

    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.3/vue.js"></script>
<div id="example">

    <div v-if="selected">

        <select v-model="selected[selector.name]" v-for="selector in selectors">
            <option :value="option" v-for="option in selector.options">
                {{option}}
            </option>
        </select>

        <p>make: {{selected.make}}<p>
        
        <p>fuel: {{selected.fuel}}</p>
        
        <pre>{{ selected }}</pre>

    </div>

</div>
tony19
  • 125,647
  • 18
  • 229
  • 307
GuyC
  • 6,494
  • 1
  • 31
  • 44
  • ah, I thought that only applied to arrays, I will give it a try. A link to the docs would be great in an answer like this – Pete Dec 01 '16 at 09:23
  • 1
    it actually applies more to objects than it does arrays. Arrays have mutation methods and such which allow you to make changes and keep the array reactive. Vue however will not detect additional keys on objects and make them reactive – GuyC Dec 01 '16 at 09:31
  • yeah so I can't use this as `v-model` can I, I'd have to do it in a function outside of the markup – Pete Dec 01 '16 at 09:33
  • I'm still a bit lost on how I can attach that to the select/option - I see why it's not working but where can I work the `this.set...` into it? – Pete Dec 01 '16 at 09:54
  • updated the answer to show you how this can work, P.S was already working on it - didn't take me 38secs! – GuyC Dec 01 '16 at 09:55
  • ha, great thanks @Guy! ok that seems obvious now, I clearly need much more coffee. thanks a lot. – Pete Dec 01 '16 at 10:00