Vuejs radio buttons checked if v-model is an array - vue.js

How can i have checked radio button in v-for, if i my v-model is an array?
my data:
data() {
return {
persons: {
name: [],
surname: [],
sex: [],
}
}
}
and my radio:
<template v-for(person, person_index) in persons>
<div class="switch-sex">
<input type="radio" name="sex" :id="'male'+person_index" value="male"
v-model="persons.sex[person_index]">
<label :for="'male' + person_index">M</label>
<input type="radio" name="sex" :id="'female' + person_index"
value="female" v-model="persons.sex[person_index]">
<label :for="'female' + person_index">F</label>
</div>
</template>
I need my first radio ( male) be checked in each person inside v-for

If I don't misunderstood your question and your objective, your doing dynamic forms for multiple persons then try like this
Template
//n and index used for 0-based looping
<div v-for="(n, index) in noOfPersons" :key="index">
Person {{ index + 1 }}
<div class="switch-sex">
<input type="radio" :name="'sex'+(index+1)" value="male" v-model="persons[index].sex">
<label >Male {{index+1}}</label>
</div>
<div>
<input type="radio" :name="'sex'+(index+1)" value="female" v-model="persons[index].sex">
<label >Female {{index+1}} </label>
</div>
</div>
Script (just an example to show its checked)
data() {
return {
noOfPersons: 2,
persons: [
{name: '', surname: '', sex: 'male'},
{name: '', surname: '', sex: 'female'},
]
}
}
For those using Vuetify.js (it's different approach with v-model on the v-radio-group wrapper)
<v-radio-group v-model="persons[index].sex" :mandatory="false">
<v-radio label="Male" :value="1" color="blue"></v-radio>
<v-radio label="Female" :value="0" color="blue"></v-radio>
</v-radio-group>
Here's the Code Pen
NOTE. It is recommended to use binary (0/1) data like 0 for male or 1 for female or other numbers like 1/2 Database Storage / ISO 5218 or dummy variables. Here's explanation

Related

Input binding in v-for

I want to bind values from input radio button generated by v-for.
I have tried use v-model to bind them with variables question_1, question_2, question_3 in data().
<template>
<div id="radioButtons">
<div v-for="(question_obj, index) in questions" :key="index" class="form-group form-radio">
<span>{{ question_obj.question }} {{ question_obj.variable }}</span>
<br>
<label>
<input type="radio" :name="question_obj.variable" v-model="question_obj.variable" value="yes" >
<span>Yes</span>
</label>
<label>
<input type="radio" :name="question_obj.variable" v-model="question_obj.variable" value="no" >
<span>No</span>
</label>
</div>
</div>
</template>
<script>
export default {
name: 'radioButtons',
data () {
return {
question_1: '',
question_2: '',
question_3: '',
questions: [
{ question: 'Question 1', variable: 'question_1'},
{ question: 'Question 2', variable: 'question_2'},
{ question: 'Question 3', variable: 'question_3'},
]
}
}
}
</script>
I would like the value to be saved in data () after selecting the radio button.
Use index in v-for for v-model changes so it changes question object properties, not their instance:
new Vue({
el: '#app',
data () {
return {
//question_1: '', //don't need question_1, 2 and 3
// question_2: '',
// question_3: '',
questions: [
{ question: 'Question 1', variable: 'no'}, //notice that I have stored default values in question. Also consider renaming variable to answer to preserve good semantics.
{ question: 'Question 2', variable: 'yes'},
{ question: 'Question 3', variable: 'no'},
]
}
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id="radioButtons">
<div v-for="(question_obj, index) in questions" :key="index" class="form-group form-radio">
<span>{{ question_obj.question }} {{ question_obj.variable }}</span>
<br>
<label>
<input type="radio" :name="'question-' + index" v-model="questions[index].variable" value="yes" :checked="question_obj.variable == 'yes'">
<span>Yes</span>
</label>
<label>
<input type="radio" :name="'question-' + index" v-model="questions[index].variable" value="no" :checked="question_obj.variable == 'no'">
<span>No</span>
</label>
</div>
</div>
</div>
Note: There is no need to store answers in question_1, question_2, question_3, since you might have more than 3 questions, and it won't be efficient.
Better way is to store answer in variable property value.
So in component it will look like this:
<template>
<div id="radioButtons">
<div v-for="(question_obj, index) in questions" :key="index" class="form-group form-radio">
<span>{{ question_obj.question }} {{ question_obj.variable }}</span>
<br>
<label>
<input type="radio" :name="'question-' + index" v-model="questions[index].variable" value="yes" :checked="question_obj.variable == 'yes'">
<span>Yes</span>
</label>
<label>
<input type="radio" :name="'question-' + index" v-model="questions[index].variable" value="no" :checked="question_obj.variable == 'no'">
<span>No</span>
</label>
</div>
</div>
</template>
<script>
export default {
name: 'radioButtons',
data () {
return {
//question_1: '', //don't need question_1, 2 and 3
// question_2: '',
// question_3: '',
questions: [
{ question: 'Question 1', variable: 'no'}, //notice that I have stored default values in question. Also consider renaming variable to answer to preserve good semantics.
{ question: 'Question 2', variable: 'yes'},
{ question: 'Question 3', variable: 'no'},
]
}
},
}
</script>
<style>
</style>
Try this code.
export default {
name: 'radioButtons',
data () {
return {
radio_data: {
'question_1': '',
'question_2': '',
'question_3': ''
},
questions: [
{ question: 'Question 1', variable: 'question_1'},
{ question: 'Question 2', variable: 'question_2'},
{ question: 'Question 3', variable: 'question_3'}
]
}
},
}
<template>
<div id="radioButtons">
<div v-for="(question_obj, index) in questions" :key="index" class="form-group form-radio">
<span>{{ question_obj.question }} {{ question_obj.variable }}</span>
<br>
<label>
<input type="radio" :name="'question-' + index" v-model="radio_data[questions[index].variable]" value="yes" :checked="question_obj.variable == 'yes'">
<span>Yes</span>
</label>
<label>
<input type="radio" :name="'question-' + index" v-model="radio_data[questions[index].variable]" value="no" :checked="question_obj.variable == 'no'">
<span>No</span>
</label>
</div>
</div>
</template>
Store your key, question, and answer in the same object in your array of questions. If you want to get the selected values as an object, use a method to reduce them into an appropriate value. In the example code below I've included such a method, as well as live JSON output to see the result.
<template>
<div id="radioButtons">
<div
v-for="row in questions"
:key="row.key"
class="form-group form-radio"
>
<span>{{ row.question }} {{ row.key }}</span>
<br />
<label>
<input
type="radio"
:name="row.key"
v-model="row.answer"
value="yes"
/>
<span>Yes</span>
</label>
<label>
<input
type="radio"
:name="row.key"
v-model="row.answer"
value="no"
/>
<span>No</span>
</label>
</div>
<pre>{{ JSON.stringify(getAnswers(), null, 2) }}</pre>
</div>
</template>
<script>
export default {
name: "radioButtons",
data() {
return {
questions: [
{ key: "question_1", question: "Question 1", answer: null },
{ key: "question_2", question: "Question 2", answer: null },
{ key: "question_3", question: "Question 3", answer: null },
],
};
},
methods: {
getAnswers() {
return this.questions.reduce((acc, cur) => {
acc[cur.key] = cur.answer;
return acc;
}, {});
},
},
};
</script>

create vue.js v-model from dynamci value

I am generating a some checkbox dynamically. Now I need to create v-model dynamic.
<div class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="v in alldietry" :key="v">
<input type="checkbox" v-model="userinfo.{{#Here will be the value}}" value="" id="Vegetarian">
<label for="Vegetarian">{{v.title}}</label>
</div>
</div>
into the v-model I have try v-model="userinfo.{{xyz}}" its shows error.
You can't use {{ }} interpolation inside attributes.
The v-model value is a javascript expression, so instead of
v-model="userinfo.{{xyz}}"
you can just do
v-model="userinfo[xyz]"
as you would normally do in javascript when accessing a dynamic property of an object.
To bind dynamic object to model, you need to access to key shared by the model value and the set of data used to display your list.
let vm = new Vue({
el: '#app',
data: {
userinfo: {
0: '',
1: ''
}
},
computed: {
alldietry() {
return [
{
id: 0,
title: 'Title'
},
{
id: 1,
title: 'Title'
}
]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app" class="form-group input-group">
<label class="form-group-title">DIETARY PREFERENCES</label>
<p>Please mark appropriate boxes if it applies to you and/or your family</p>
<div class="check-group" v-for="(v, index) in alldietry" :key="index">
<input type="checkbox" v-model="userinfo[v.id]" value="" :id="v.id">
<label :for="v.id">{{v.title}}</label>
</div>
{{ userinfo }}
</div>

vue js v-for input type with v-model

I want two input field with name1 and name2, name1 = Peter, name2= Kitty. But i have not any idea to handle it.
<div v-for="list in item">
<input type="text" id="name" name="name" v-model="name"></>
{{list.name}}
</div>
data() {
return {
item: [{ name: 'Peter' },{ name: 'Kitty' }],
name: ''
}
}
here i want:
input type="text" id="name1" name="name2" v-model="name1"><--Show Peter
input type="text" id="name1" name="name2" v-model="name2"><--Show Kitty
The problem is with your v-model. You need to bind it to the name attribute of the object in your item array.
Change v-model="name" to v-model="list.name"
JSFiddle example
If you have multiple input elements you want to display, you should also have multiple slots of where you will put the data. For example, you could do it like this, by adding a value property to the item element:
new Vue({
el: '#app',
data: {
items: [
{ name: 'Peter', value: '' },
{ name: 'Kitty', value: '' }
],
},
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div v-for="item in items">
<label>{{item.name}}:</label>
<input type="text" name="item.name" v-model="item.value">
</div>
<!-- Output for debugging purposes -->
{{items}}
</div>
<div v-for="list in item">
<input type="text" v-model="list.name"></>
{{list.name}}
</div>
data() {
return {
item: [{ name: 'Peter' },{ name: 'Kitty' }],
name: ''
}
}
<div v-for="list in item" :key="list.id">
<input type="text" :id="list.name" :name="list.name" :v-model="list.name"/>
{{ list.name }}
</div>

Store checked values with Vuejs

I have some very simple Vue.js code in a multi-step form. I am trying to store the values temporarily until the user reaches the end of the form.
However, I am getting some errors with a checkbox value binding.
My form looks like the following:
<div v-for="item in items">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" v-model="checkedItems" :value="item.id">
{{ item.text }}
</label>
</div>
And my Vue:
new Vue({
el: '#multistep-form',
data: {
items: [
{id: 0, text: 'Item 1'}
{id: 1, text: 'Item 2'}
{id: 2, text: 'Item 3'}
],
checkedItems: [],
}
});
When I click the items, it is creating empty checkboxes. These get deleted when I uncheck the items as in the attached image.
Anyone know why this is happening and how I can fix it?
You're specifying array as v-model where it should be one of the indices of array. Try the following:
<div v-for="(item, index) in items">
<label class="form-check-label">
<input type="checkbox" class="form-check-input" v-model="checkedItems[index]" :value="item.id">{{ item.text }}
</label>
</div>

Vue js v-for v-bind not unique

I'm trying to create a form where I have a select list (fetched from API) and user can add items into a seperate array from this list. New array is also rendered via v-for and uses v-model to edit some additional data.
For example I have a list of goods/services defined beforehand which will be rendered into select option block. Now user can select one of these products and add them to a invoice. After adding (pushed to a new array), user must be able to make some additional changes.
<select class="form-control" v-model="selectedServiceId">
<option v-for="service in services" :value="service._id">{{service.name}}</option>
</select>
<button type="button" class="btn btn-primary" v-on:click="addService">Add</button>
add service method:
addService() {
for (var i = 0; i < this.services.length; i++) {
if (this.services[i]._id == this.selectedServiceId) {
this.services_goods.push(this.services[i])
break;
}
}
}
And now I want to render the list I've pushed into:
<ul>
<li v-for="(item, key) in services_goods">
<span>{{item.name}}</span>
<label for="itemPrice">Price €
<input id="itemPrice" v-model="item.price">
</label>
<label for="itemQty">Quantity
<input type="number" min="1" id="itemQty" v-model="item.quantity">
</label>
<div>
<button type="button" v-on:click="removeService(item._id)">X</button>
</div>
</li>
</ul>
everything is fine up until I add the same item twice and try to modify the price for one of them - it changes price for both.
The reason it changes the price for both is that they are the same object. When you insert an object into an array, the value in the array is a reference to the object. You have two references to the same object.
Each object you insert into the array should be newly created, with contents copied from the selected item.
new Vue({
el: '#app',
data: {
selectedServiceId: null,
services: [{
_id: 1,
price: 1,
quantity: 1,
name: 'First'
},
{
_id: 2,
price: 2,
quantity: 2,
name: 'Second'
}
],
services_goods: []
},
methods: {
addService() {
const foundGood = this.services.find((s) => s._id == this.selectedServiceId);
// Object.assign copies an object's contents
this.services_goods.push(Object.assign({}, foundGood));
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<div id="app">
<select class="form-control" v-model="selectedServiceId">
<option v-for="service in services" :value="service._id">{{service.name}}</option>
</select>
<button type="button" class="btn btn-primary" v-on:click="addService">Add</button>
<ul>
<li v-for="(item, key) in services_goods">
<span>{{item.name}}</span>
<label for="itemPrice">Price €
<input id="itemPrice" v-model="item.price">
</label>
<label for="itemQty">Quantity
<input type="number" min="1" id="itemQty" v-model="item.quantity">
</label>
<div>
<button type="button" v-on:click="removeService(item._id)">X</button>
</div>
</li>
</ul>
</div>