I have these lines inside my component:
<li
v-for="(c, i) in choice[messagesRobot[numMessage].choice]"
:key="`choice-${choice[messagesRobot[numMessage].choice]}-${i}`">
<input
#change="changeValue($event, messagesRobot[numMessage].choice)"
:value="c.id"
type="checkbox"
:name="choix[messagesRobot[numMessage].choice]"
:id="`c-${choix[messagesRobot[numMessage].choice]}-${i}`">
<label :for="`c-${choix[messagesRobot[numMessage].choice]}-${i}`">
{{ c.nom }}
</label>
</li>
As you can see, there are a lot of computed properties. What I would like is to update the model when the user changes the value. The problem is that I can't use something like :v-model="xxx", so I have to capture the #change event. I wrote this:
function changeValue(e, v) {
console.log(v);
console.log(JSON.stringify(e.target.value));
}
The second line only gives me the last element the user selected or unselected, what I would like is to get ALL the values of the checkboxes, in an array, as it would do if I could use a v-model.
Thanks in advance for your help :)
I think you could do something like this
<li
v-for="(c, i) in choice[messagesRobot[numMessage].choice]"
:key="`choice-${choice[messagesRobot[numMessage].choice]}-${i}`">
<input
#change="changeValue($event, messagesRobot[numMessage].choice, i)"
:value="c.id"
type="checkbox"
:name="choix[messagesRobot[numMessage].choice]"
:id="`c-${choix[messagesRobot[numMessage].choice]}-${i}`">
<label :for="`c-${choix[messagesRobot[numMessage].choice]}-${i}`">
{{ c.nom }}
</label>
</li>
data() {
return {
valuesArray: []
}
}
function changeValue(e, v, index) {
this.valuesArray[index] = e.target.value;
console.log(v);
console.log(JSON.stringify(e.target.value));
}
then your valuesArray would have all the checked values.
Why can't you just use v-model?
Related
I have an array with many checkbox.
<li v-for='item in resultQuery' :key='item.id'>
<label class='custom-checkbox'>
<input type='checkbox' :value='item.id' v-model='checkBrands'>
<span #click='loadProducts(item.seoName)>{{ item.title }}</span>
</label>
</li>
I need to get true or false (depends on checkbox). How can I do this without affecting the v-model? (Use it to transfer an array of selected checkbox).
Needed to trigger a specific mutation
.then((response) => {
if(true) {
this.$store.commit(
'showFilteredList',
response.data.items
);
} else {
this.$store.commit(
'deleteCheckboxItems',
response.data.items
);
}
});
You can using #change on checkbox.
Example: https://codepen.io/koei5113/pen/ZEXLLgL
<input type='checkbox' :value='item.id' v-model='checkBrands' #change="changeEvent">
methods: {
...,
changeEvent($event) {
console.log($event.target.checked);
}
}
In this example you can see your v-model still working and you still can check checkbox status by the change event.
v-model ignore the :value in the input. You need to use :checked and #change
For example, and when you emit the change event use your function.
<input type="checkbox" :checked="value" #change="changeArrayNotValue" />
So I have 2 checkbox inputs for each element in an array. The first represents a field in a form and the second represents the fact that the field is required or not, I need to construct and array of objects like so
[
{
name: 'fieldName',
required: true
},
{
name: 'anotherFieldName'
}
]
If the first checkbox is checked I need to add an object with the "name" property in my array, and if the second one is checked too I also need to add the "required" field.
try this
<li v-for="(item, index) of items">
{{ item.prop2 }}
<input type="text" v-model="items[index].prop2">
</li>
or
<li v-for="(item, index) of items">
{{ item.prop2 }}
<input type="text" #input="updateMyProp(index)">
</li>
...
methods: {
updateMyProp ($event, index) {
// your update logic here
// you can use 'this.items', Object.assign, Vue.set, etc... to update your value
}
...
I need a simple v-for to render object properties in a list.
<div
v-if="profileData && profileData.length > 0"
>
<ul
v-for="value in profileData"
:key="value.id"
>
<li>{{value.id}}</li>
</ul>
</div>
In the script:
profileData: {},
created() {
const userId = this.$route.params.userId
const currentUser = this.$store.getters.currentUser
const profileData = this.$store.getters.profileData
console.log('profileData in seeProfile: ', profileData) }
(profileData comes from an api response)
I did exactly the same in two other pages (just rendering different objects) and it worked.
With this code, in the console I get value is undefined.
If I remove :key="value.id" (it becomes red in the editor but it still works), and instead of the list items I type only {{ value }}}, then the object properties get rendered ( but in the ugly format of a js object). How can it be? What am I doing wrong?
Thank you
Your v-if will never show even if profileData has data, because you can't directly check for the length of an Object in javascript.
A few things:
You can't check for the length of an Object, it will return undefined. If you must use an object, then you'd have to check for Object.keys(obj).length.
let obj = {
first: {
name: "first",
meta: "data"
},
second: {
name: "second",
meta: "data"
}
};
console.log("Object.length is: ", obj.length);
console.log("Object.keys().length is: ", Object.keys(obj).length);
You're being redundant, you don't need to check for profileData and its length (and you don't need to > 0), you could simply check for v-if="Object.keys(profileData).length". If the Object has zero entries, then it won't show because if(0) is false.
I'd strongly recommend to work with arrays to iterate with v-for. I'd use computed properties and return an array, and iterate through that. Object reactivity works non-intuitively in JS, so you'll be scratching your head later when you try to find out why stuff isn't updating on your view:
computed: {
listData() {
let list = Object.values(this.profileData);
return list;
}
}
In view:
<div v-if="listData.length"/>
Also, don't use the array's entry index as your :key, because if you have another array with v-for, you'll have duplicated keys in your model. I'd use something like v-for="(item, key) in list" :key="'list-item-' + key"
Put the v-for on the li, not the ul.
<ul>
<li v-for="value in profileData"
:key="value.id">{{value.id}}</li>
</ul>
Also , if your your profileData is an object and not an array, you need to decide if you want to loop through the keys or values.
<ul>
<li v-for="value in Object.values(profileData)"
:key="value.id">{{value.id}}</li>
</ul>
<ul>
<li v-for="value in Object.keys(profileData)"
:key="value.id">{{value.id}}</li>
</ul>
Or use Vue's default behavior.
<ul>
<li v-for="(value,key) in profileData"
:key="value.id">{{value.id}}</li>
</ul>
The api has been changed, so the working code is slightly different from the original one.
Here's the template:
<div
v-if="listData.length"
>
<ul>
<li>Name: <b>{{ profileData.user.first_name }}</b></li>
<li>Surname: <b>{{ profileData.user.last_name }}</b></li>
<li>Username: <b>{{ profileData.user.username }}</b></li>
<li>Car: <b>{{ profileData.if_cars_owned }}</b></li>
<li v-if="profileData.if_cars_owned === true">
Car model: {{ profileData.user_car_type }}
</li>
<li v-if="profileData.if_cars_owned === true">
Car power: {{ profileData.user_car_powered_by }}
</li>
<li>Motorcycle: <b>{{ profileData.if_motorcycle_owned }}</b></li>
<li v-if="profileData.if_motorcycle_owned === true">
Motorcycle model: {{ profileData.user_motorcycle_characteristic }}
</li>
</ul>
</div>
Script:
created(){
const profileData = this.$store.getters.profileData
this.profileData = profileData
console.log('profile data in profilo: ', profileData)
},
I've also updated
<div
v-if="listData.length"
>
and in the script
computed: {
...,
listData() {
let list = Object.values(this.profileData);
return list;
}
},
following the advice of #Adrián S. Basave.
Thanks to anyone who tried to help.
x
I populate some radio buttons from an array of options. I would like to determine which radio button was select using $refs, however when I log out the $refs it gives me all of the radio buttons.
Is it possible to just grab the select radio button using $refs? Can you some how combine event.target with the $refs or something? Furthermore how to I access parts of that ref like the class of the element that was selected. I am trying to use just vue to do this but has proven difficult.
thanks for any help you can provide.
<li
class="mc-option"
v-for="(option, i) in options"
:key="i">
<input
ref="mcOption"
type="radio"
name="option"
:id="'option-' + i"
class=""
#click="radioSelected($event)">
</li>
methods: {
radioSelected: function () {
let mcOption = this.$refs.mcOption
console.log(mcOption)
},)
}
X is your ID:
<ul>
<li v-for="x in 5">
<label :for="`radio${x}`">radio{{x}}</label>
<input type="radio" name="radio" :id="`radio${x}`" #change="getRef(`radio${x}`)" :ref="`radio${x}`">
</li>
</ul>
methods: {
getRef (ref) {
console.log(this.$refs[ref])
}}
This is happening since all the generated options are having the same ref ids. You could come over this with the following code.
TEMPLATE
<li class="mc-option" v-for="(option, i) in options" :key="i">
<input :ref="['mcOption',i].join('-')" type="radio" name="option" :id="'option-' + i" class="" #click="radioSelected(i)"> {{i+1}}
</li>
JS
methods: {
radioSelected: function (i) {
let mcOption = this.$refs[['mcOption', i].join('-')]
console.log(mcOption)
}
}
Points to note are:
:ref
a variable ref id by using ['mcOption', i].join('-'). This actually can be anything you want (but should change for every v-for iteration).
Please let me know if it does NOT work for you.
I am trying to make a radio button checked using vuejs v-for only if my if-statement is true. Is there a way to use vuejs' v-if/v-else for this type of problem?
in php and html I can achieve this by doing the following:
<input type="radio" <? if(portal.id == currentPortalId) ? 'checked="checked"' : ''?>>
Below is what I have so far using vuejs:
<div v-for="portal in portals">
<input type="radio" id="{{portal.id}}" name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
v-if="{{portal.id == currentPortalId}}"
checked="checked">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
I know the v-if statement here is for checking whether to show or hide the input.
Any help would be very much appreciated.
You could bind the checked attribute like this:
<div v-for="portal in portals">
<input type="radio"
id="{{portal.id}}"
name="portalSelect"
v-bind:value="{id: portal.id, name: portal.name}"
v-model="newPortalSelect"
v-on:change="showSellers"
:checked="portal.id == currentPortalId">
<label for="{{portal.id}}">{{portal.name}}</label>
</div>
Simple example: https://jsfiddle.net/b4k6tpj9/
Maybe someone finds this approach helpful:
In template I assign each radio button a value:
<input type="radio" value="1" v-model.number="someProperty">
<input type="radio" value="2" v-model.number="someProperty">
Then in the component I set the value, i.e:
data: function () {
return {
someProperty: 2
}
}
And in this case vue will select the second radio button.
You can follow below option if you can adjust with your logic:
<div class="combination-quantity">
<input type="radio" value="Lost"
v-model="missing_status">
<label for="lost">Lost</label>
<br>
<input type="radio" value="Return Supplier" v-model="missing_status">
<label for="return_supplier">Return Supplier</label>
</div>
Value for missing_status could be "Lost" or "Return Supplier" and based on the value radio option will be get selected automatically.
Below is an example of keeping track of the selected radiobutton, by
applying a value binding to the object (:value="portal") and
applying a v-model binding to the currently selected object (v-model="currentPortal").
The radiobutton will be checked automatically by Vue, when the two match (no :checked binding necessary!).
Vue 3 with composition API
Vue.createApp({
setup() {
const portals = [{
id: 1,
name: "Portal 1"
}, {
id: 2,
name: "Portal 2"
}];
const currentPortal = portals[1];
return {
portals,
currentPortal
}
}
}).mount("#app");
<script src="https://unpkg.com/vue#next"></script>
<div id="app">
<template v-for="portal in portals">
<input
type="radio"
:id="portal.id"
name="portalSelect"
:value="portal"
v-model="currentPortal">
<label :for="portal.id">{{portal.name}}</label>
</template>
</div>
I would like to point out a few options when dealing with radios and vue.js. In general if you need to dynamically bind an attribute value you can use the shorthand binding syntax to bind to and calculate that value. You can bind to data, a computed value or a method and a combination of all three.
new Vue({
el: '#demo',
data() {
return {
checkedData: false,
checkedGroupVModel: "radioVModel3", //some defaul
toggleChecked: false,
recalculateComputed: null
};
},
computed: {
amIChecked() {
let isEven = false;
if (this.recalculateComputed) {
let timeMills = new Date().getMilliseconds();
isEven = timeMills % 2 === 0;
}
return isEven;
}
},
methods: {
onToggle() {
this.toggleChecked = !this.toggleChecked;
return this.toggleChecked;
},
mutateComputedDependentData() {
this.recalculateComputed = {};
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="demo">
<div>
<div>
<span>Simple Radio Group - Only one checked at a time. Bound to data.checkedData</span><br>
<label>Radio 1 - inverse of checkedData = {{!checkedData}}
<input type="radio" name="group1" value="radio1" :checked="!checkedData">
</label><br>
<label>Radio 2 - checkedData = {{checkedData}}
<input type="radio" name="group1" value="radio2" :checked="checkedData">
</label><br>
<span>Understanding checked attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-checked</span>
</div>
<br>
<div>
<span>Simple Radio - Checked bouned to semi-random computed object</span><br>
<label>Radio 1: {{amIChecked}}
<input type="radio" :checked="amIChecked">
</label>
<label>Recalculate Computed Value
<button type="button" #click="mutateComputedDependentData">Click Me Several Times</button>
</label>
</div>
<br>
<div>
<span>Simple Radio Group - v-model bound value = {{checkedGroupVModel}}</span><br>
<label>Simple Radio 1:
<input type="radio" name="vModelGroup" value="radioVModel1" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 2:
<input type="radio" name="vModelGroup" value="radioVModel2" v-model="checkedGroupVModel">
</label><br>
<label>Simple Radio 3:
<input type="radio" name="vModelGroup" value="radioVModel3" v-model="checkedGroupVModel">
</label>
</div>
<br>
<div>
<span>Simpe Radio - click handler to toggle data bound to :checked to toggle selection</span><br>
<label>Toggle Radio = {{toggleChecked}}
<input type="radio" :checked="toggleChecked" #click='onToggle()'>
</label>
</div>
</div>
</div>