In this simple exercise, we will quickly go over how we can use v-model binding on the input fields when we are generating the input fields in our markup in a loop using v-for directive.

To demonstrate let's create a simple multiple-choice quiz application where we have the questions and it's options defined in a data property inside the Vue instance.

var app = new Vue({
    el: '#app',
    data: {
        "questions": [
            { 
                "q": "What number is the letter A in the English alphabet?",
                "a": [
                    {"option": "8",      "correct": false},
                    {"option": "14",     "correct": false},
                    {"option": "1",      "correct": true},
                    {"option": "23",     "correct": false} // no comma here
                ],
            },
            { 
                "q": "Where is TajMahal?",
                "a": [
                    {"option": "Delhi",      "correct": false},
                    {"option": "Agra",     "correct": true},
                    {"option": "Mumbai",      "correct": false},
                    {"option": "Kochin",     "correct": false} // no comma here
                ],
            },
            { 
                "q": "Where is GateWay Of India?",
                "a": [
                    {"option": "Delhi",      "correct": false},
                    {"option": "Agra",     "correct": false},
                    {"option": "Mumbai",      "correct": true},
                    {"option": "Kochin",     "correct": false} // no comma here
                ],
            },
        ],
    },
});

And in our HTML markup, we generate the list of questions along with their options using v-for directive.

<template v-for="(question, index) in questions">
    <h4>{{question.q}}</h4>
    <template v-for="options in question.a">
        <input type="radio" :name="'question'+index" :value="options.option" /> {{options.option}} <br/>
    </template>
    <br/>
</template>

We have used two loops in this one to loop through all the possible questions and another to loop through its possible responses.

What about v-model binding? Since the number of questions and their responses can be dynamic how do we bind the inputs to data properties in our Vue Instance?

There are two ways to achieve this.

1. Dynamic v-model binding in an object property.

One way to achieve two-way binding is to define an empty object in your Vue Instance and then in your HTML markup use the array notation to store the values.

Here's how.

Define this additional property in Vue Instance

...
responses: {}
...

...
<input type="radio" :name="'question'+index" :value="options.option"  v-model="responses['question'+index]"/> {{options.option}} <br/>
...

Now when the user selects responses, It will be dynamically assigned inside the responses object.

You can get the individual responses by looping through the object on submitting

        methods:{
            submit(){
                for (var key of Object.keys(this.responses)) {
                    console.log(key + " -> " + this.responses[key])
                }
            }
        }

1. Dynamic v-model binding in an array property.

...
responses: []
...

...
<input type="radio" :name="'question'+index" :value="options.option"  v-model="responses[index]"/> {{options.option}} <br/>
...

Note that we can only use the numerical index in case of an array.

That's all about Dynamic V-model name binding.

Comments