Using vue, determine which radio input is selected by accessing $refs - vue.js

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.

Related

Get all selected values on change with VueJS 3

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?

Can't select chechbox with v-model in VueJS

I have a checkbox as a feature filter for a real estate agency site.
From the database comes the list of categories with their respective characteristics:
public function get_categories(Request $request)
{
$categories = Category::with('features')->get();
return response()->json([
'validation' => true,
'categories' => $categories
]);
}
In the Vue template, I have an accordion with UIKit.
I have one accordion header per category that I walk through using a v-for
Then inside the body of the accordion I have the checkboxes that correspond to the characteristics that belong to that category
<li
v-for="category in categories"
:key="category.id">
<a
href="#"
class="uk-accordion-title">
{{ category.name }}
</a>
<div class="uk-accordion-content">
<div uk-grid>
<div
class="uk-width-1-1 uk-margin-small"
v-for="feature in category.features"
:key="feature.id">
<label>
<input
:id="'feature_' + feature.id"
class="uk-checkbox"
type="checkbox"
name="features"
:value="feature.id"
v-model="features"
#change="filterUpdate"> <!-- ID hacer que este sea venga de la BD -->
{{ feature.name }}
</label>
</div>
</div>
</div>
</li>
To load the categories of course I have a method that is responsible for making the request when creating the component
layoutLoadCategories() {
axios.get('api/layout/get/categories').then( res => {
this.categories = res.data.categories;
});
},
The problem is that when I try to click on a checkbox, nothing happens. Not selected
When you are using v-model you no need to use :value and moreover since its a checkbox input you v-model variable should hold only boolean value (ie) either true or false
<input
:id="'feature_' + feature.id"
class="uk-checkbox"
type="checkbox"
name="features"
v-model="features" // here I guess features is an object or array...so assign a variable that is of type Boolean
#change="filterUpdate">
I have already worked out, in the form tag I had # click.prevent
I have removed the .prevent and it already works
Before:
<form id="filter_form" action="/property-browser" method="get" #click.prevent="filterUpdate">
After:
<form id="filter_form" action="/property-browser" method="get" #click="filterUpdate">

Set focus to first item in v-for using vue

I have a vue app and I'm trying to set the focus to the first item in my v-for list but struggling
HTML
<div class="input-group-append">
<button class="btn btn-light" type="submit" style="border: 1px solid lightgray" #click.prevent="findTest">
<i class="fas fa-search"></i>
</button>
</div>
<div v-if="this.Tests.length >= 2" class="list-group accList">
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" :ref="i" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
</div>
Note the word 'test' has replaced my actual values
I have tried using the following in my method which is called on button click but I keep getting get an error
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
}
}
}
Error
I am relativly new to vue but I have been able to set my focus using:
this.$refs.[INPUT_NAME].$el.focus()
But it doesn't like me using a number
this.$refs.0.$el.focus() //0 being the index number
As WebStorm complains saying:
Expecting newline or semicolon
console.log(this.$refs)
When using v-for, ref maybe array of refs.
Template: use ref="tests" instead of :ref="i"
<a v-for="(test, i) in tests" :key="i" class="list-group-item list-group-item-action" ref="tests" :class="{ 'active': i === 0 }" #click.prevent="selectTest(test)">
{{ test.test1 }} ({{ test.test2 | capitalize }})
</a>
Script
this.$refs.tests[0]
I guess its undefined because you try to access the element while the v-for loop didnt finished its rendering
Try this:
methods: {
findTest() {
axios.get(END_POINT).then((response) => {
...SOMEOTHER CODE
this.$nextTick(()=> {
//put your code here
//this.$refs.0.$el.focus()
//this.$refs.0.focus();
//this.$refs.a.$el.children[0].focus();
})
}
}
}
Put your code into $nextTick() that should ensure that its get executed when the loop is done

vuejs set a radio button checked if statement is true

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>

aurelia - dropdown not selecting value from db on load

I am using aurelia and have a dropdown. It passes the GroupId correctly back into my save function however it isnt selecting anything when editing a item.
return this.dataContext.getBaseContent(this.id)
.then(baseContent => this.baseContent = baseContent);
<dropdown disabled.bind="readonly" options.bind="core.GetVariableGroups()" selected.bind="baseContent.GroupId" />
HTML of dropdown
<div class="chosen-container chosen-container-single" style="width: 877px;" title="">
<a class="chosen-single chosen-default" tabindex="-1">
<span>Choose an option...</span>
<div><b></b></div>
</a>
<div class="chosen-drop">
<div class="chosen-search"><input type="text" autocomplete="off"></div>
<ul class="chosen-results">
<li class="active-result au-target" data-option-array-index="1">Option 1</li>
<li class="active-result au-target" data-option-array-index="2">Option 2</li>
<li class="active-result au-target" data-option-array-index="3">Option 3</li>
</ul>
</div>
</div>
<template>
<select disabled.bind="disabled" class="form-control" data-placeholder.bind="placeholder" value.bind="selected">
<option repeat.for="option of options" value.bind="option.Id" text.bind="option.Name"></option>
</select>
</template>
{"$type":"Admin.Contracts.Pocos.Development.ApplicationVariables.BaseContentModel, Admin.Contracts","Id":441,"GroupId":1,"GroupName":"Option 1"
Ive found the issue, unsure how to solve it. Its already bond the values before it goes off and grab the data from the db. I need it to rebind on 'complete' unsure how to do this though.
This is required: add just below the constructtor, you need to trigger a chosen:update.
selectedChanged(){
// if chosen item isnt = selected then set it
var currentSelected = $('select', this.element).find(':selected').val();
if(currentSelected != this.selected) {
if(this.options.some(o => o.Id == this.selected)){
$('select', this.element).val(this.selected);
$('select', this.element).trigger("chosen:updated");
}
else{
// new selected isnt in list of options..
// set back to prev value
this.selected = currentSelected;
}
}
}