Retrieving text of select element - vue.js

When binding a <select> element using vue.js's v-model, how would you get the selected option text as opposed to the selected option value?
In HTML:
<select v-model="selected" options="myOptions"></select>
In JS:
myOptions: [{ text: 'Blue', value: '1' }, { text: 'Green', value: '2' }]
What I would want to retrieve is both the text 'Blue' as well as the value '1' by doing something like {{ selected.text }} or {{ selected.value }}. However, you can only do {{ selected }} which returns the selected value by default.
Ref: Vue.js guide for Dynamic Select Options

You can just use a filter, like this:
html:
<div id='vm'>
Formatted value:<b> {{city | cityFormatter}} </b><br/>
<br/>
<select v-model="city" options="cities"></select>
</div>
js:
var vm = new Vue({
el: '#vm',
data: {
city: 'city1',
cities: [{text: 'Toronto', value: 'city1'},
{text: 'Orleans', value: 'city2'}]
},
filters: {
cityFormatter: function(val) {
var newVal = '';
this.cities.map(function(el){
if (val == el.value){
newVal = el.value + ' ' + el.text;
}
});
return newVal;
}
}
});
Working example:
http://jsfiddle.net/qfy6s9Lj/9/

Actually, you could try combine jquery or just native js code
The solution with jQuery
html:
<div id='example'>
<select v-model="selected" options="myOptions"></select>
</div>
js:
var vm = new Vue({
el: '#example',
data: {
...
},
computed: {
selectedtext: {
cache: false,
//get selectedtext by jquery
get: function(){ return $(this.$el).find(":selected").text();}
}
},
});
The solution without jquery
html:
<div id='example'>
<select ref="ddl" v-model="selected" options="myOptions"></select>
</div>
js:
var vm = new Vue({
el: '#example',
data: {
...
},
computed: {
selectedtext: {
cache: false,
//get selectedtext directly
get: function(){
var ddl = this.$refs.ddl;
return ddl.options[ddl.selectedIndex].text;
}
}
},
});
Moreover, you could create a component for reusing logic and achieve the purpose of accessing the selected value by {{ selected.text }} or {{ selected.value }}.

An answer for Vue 2+
I was interested to come across this question as I'm currently evaluating Vue and React, and researching the comparative ease of getting current selection (not just dropdowns, but the UI generally).
What I found was that things have changed a lot since these posts in May-July 2015, when the latest version of Vue was 0.12. The JSFiddle in #swift's answer still works today because it pulls in Vue 0.12.
Using today's Vue, currently version 2.6, I found a solution that's relevant to people facing the same question today. It's interesting that using 2.6, the markup under discussion won't even get as far as initializing the options:
<select v-model="selected" options="myOptions"></select>
After digging into this, I found that although options is a valid HTML DOM property of the select element, and hence is accessible from JavaScript, it seems Vue no longer supports initializing it in markup like this. Instead, we add traditional HTML option elements. Per https://v2.vuejs.org/v2/guide/forms.html:
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
On first sight, this change seems a backward step. But in fact, remembering that we can use v-for and v-bind, I think it makes things more flexible. To demonstrate why I think that, I will first show the example given at the same linked page:
HTML
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
JS
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
It can be seen in the HTML that this binds the selected value of the dropdown to the Vue instance's selected property (using v-model="selected"), binds the individual option values to the value of each option (using v-bind:value="option.value"), and finally binds the individual option texts to the text that will be displayed (using {{ option.text }}).
It's only a small step further to bind selected to a different option property, be it text, id or whatever properties your option object may have, or--and here's the thing--to the option object itself. Being able to access the option itself as the selected value means we can access all of its properties, rather than only the property we chose to bind to:
HTML
<div id='vm'>
<select id="ddl1" v-model="ddl1selecteditem">
<option v-for="option in options1" v-bind:value="option">
{{ option.txt }}
</option>
</select>
<span>selected item: text='{{ ddl1selecteditem.txt }}', id={{ ddl1selecteditem.id }}</span>
</div>
JS
var vm = new Vue({
el: '#vm',
data: {
options1: [
{ txt: 'One', id: 1 },
{ txt: 'Two', id: 2 },
{ txt: 'Three', id: 3}
],
ddl1selecteditem: {}
}
});
vm.ddl1selecteditem = vm.options1[0];

Related

Bootstrap vue selecting the object from a list of objects b-form-select

Even though I got the solution to my problem I'm slightly unsatisfied with how it's solved. Is there a way to make this simpler? As in, ideally I would have similar html and the only thing I would do is make a call to api to get the teachers and immediately assign them to this.teachers instead of having to iterate through them to make an untyped array of some new object.
HTML:
<b-form-select
v-model="selectedTeacher"
:options="teachers"
value-field="teacher" //NOT teacher.id, I want the object itself
text-field="teacher.name">
</b-form-select>
JS
var dbTeachers: Teacher[] = await getTeachers();
dbTeachers.forEach(teacher => {
this.teachers.push(new Object({
teacher: teacher ,
name: teacher.name
}));
});
You can bind the entire object to the value of an <option> tag. So instead of using the options prop you would manually create the <option> using the v-for directive.
That way you'll get the entire object in the <b-form-select>'s v-model.
new Vue({
el: "#app",
data() {
return {
selectedItem: null,
options: [
{ id: 1, name: 'Mike Macdonald', age: 42 },
{ id: 2, name: 'Larsen Shaw', age: 27 },
{ id: 3, name: 'Jami Cord', age: 81 },
],
}
}
})
<link href="https://unpkg.com/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://unpkg.com/vue#2.6.12/dist/vue.min.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.21.2/dist/bootstrap-vue.js"></script>
<div id="app" class="p-3">
<b-form-select v-model="selectedItem">
<option :value="null" disabled>-- Please select an option --</option>
<option v-for="option in options" :value="option">
{{ option.name }}
</option>
</b-form-select>
Selected option: {{ selectedItem }}
</div>

Vue multiple select form independent from each other

I need a solution how to make as many select form as my option data length and each form must be independent from each other. It means that if i chooce selected value in one form it must do not overide selected value in others form. Also i need pre-set selected value in each form (for the first form it need to show selected first choice, for second = second choice and so on.)
var app = new Vue({
el: "#app",
delimiters: ["[[", "]]"],
data: {
selected: '',
options: [
{ id: 20 , supp_name: 'test1' },
{ id: 21 , supp_name: 'test2' },
{ id: 34 , supp_name: 'supertest' },
]
},
})
<div margin="20px" v-for='option in options'>
<form action="">
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.supp_name">
[[option.supp_name]]
</option>
</select>
<span>Chosen: [[selected]]</span>
</form>
</div>
It display 3 forms but when I make a choice in on one form it override all forms. How could it be fixed?
You will need as many selected references as there are forms.
For example
var app = new Vue({
el: "#app",
delimiters: ["[[", "]]"],
data: {
selected: [], // make selected an array
options: [{"id":20,"supp_name":"test1"},{"id":21,"supp_name":"test2"},{"id":34,"supp_name":"supertest"}]
},
watch: {
options: {
immediate: true,
handler (options) {
// initialise to the "supp_name" from options
this.selected = options.map(({ supp_name }) => supp_name)
}
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<div v-for="(_, i) in selected">
<form action="">
<select v-model="selected[i]">
<option v-for="option in options" :value="option.supp_name">
[[ option.supp_name ]]
</option>
</select>
<span>Chosen: [[ selected[i] ]]</span>
</form>
</div>
<pre>selected = [[ selected ]]</pre>
</div>
This synchronises the selected array to be the same length as options then binds each form's <select> to the array index.

Vue.js custom component with HTML <select> and v-model (W3C compliant)

I'm new to Vue.js (using Nuxt.js) and what I'm trying to achieve is to have a Select component that I can reuse everywhere and is W3C compliant.
With the help of #Jasmonate answers, I managed to create this component, it's working. But the value attribute is still visible in the source code and so isn't W3C compliant. Maybe the problem is coming from somewhere else in the project ?!
Parent component
<custom-select
:options="options"
v-model="selectedOption"
></custom-select>
<span>Selected : {{ selectedOption }}</span>
<script>
data() {
return {
selectedOption: "A",
options: [
{ label: "One", value: "A" },
{ label: "Two", value: "B" },
{ label: "Three", value: "C" }
],
};
}
</script>
custom-select.vue
<template>
<select :value="value" #input="clicked">
<option
v-for="option in options"
:key="option.label"
:value="option.value"
>
{{ option.label }}
</option>
</select>
</template>
<script>
export default {
props: {
value: {
required: true
},
options: {
type: Array,
required: true
}
},
methods: {
clicked($event) {
this.$emit("input", $event.target.value);
}
}
};
</script>
I read those documentation pages:
Form Input Bindings
Components Basics
And also looked around the web to find example of v-model in a custom component, but it's always about the input tag. The only example I found about a custom select with v-model isn't actually a select tag, like the Vue Select plugin or this thread on StackOverflow.
v-model is syntax sugar. By default, the value is a prop that has the name value, and it changes (two-way-binding) whenever the event input is emitted.
Also, v-model is bound on the select element, not option.
Your code can be modified as such:
<template>
<select :value="value" #input="clicked">
<option
v-for="option in options"
:key="option.label"
:value="option.value"
>
{{ option.label }}
</option>
</select>
</template>
<script>
export default {
props: {
value: {
required: true
},
options: {
type: Array,
required: true
}
},
methods: {
clicked($event) {
this.$emit('input', $event.target.value);
}
}
};
</script>
Documentation here: https://v2.vuejs.org/v2/guide/components.html#Using-v-model-on-Components
You can also change the prop name and event name that v-model uses, see: https://v2.vuejs.org/v2/guide/components-custom-events.html#Customizing-Component-v-model

VueJs drop-down first item not selected on initial load

I have a drop-down option working with an array of items. I want to add the first selection/option as Select a Site.
When the element is rendered, the drop-down does not show the Select a Site initially. The drop-down element does have the array in the drop-down options.
The first image shows the initial state of the drop-down (looks
empty, but its not)
The second image is when the drop-down element is
when selected.
How can I the drop-down working with the Select a Site shown as the first option?
<select id="ddSite" name="ddSite" class="form-control m-b-10" v-on:change="onChangeSite($event)" v-model="ddSite">
<option :value="null">-- Select a Site --</option>
<option v-for="option in sites" v-bind:value="option.SiteId">
{{ option.SiteName }}
</option>
</select>
new Vue({
el: '#app',
data: {
sites: [],
ddSite:""
},
mounted() {
axios.get("/api/sites/" + this.companyid)
.then(response => {
this.sites = response.data
});
},
methods: {
onChangeSite: function (e) {
var self = this;
var siteid = e.target.value;
var sitename = e.target.options[e.target.options.selectedIndex].text;
},
In your code, you're binding the select's value to ddSite.
The -- Select a Site -- option has a value of null, but your ddSite data starts off as an empty string.
In order to have that option selected initially, you must init ddSite as null:
new Vue({
el: '#app',
data: {
ddSite: null,
sites: [{
SiteId: 1,
SiteName: 'Google',
},
{
SiteId: 2,
SiteName: 'Facebook',
},
{
SiteId: 3,
SiteName: 'StackOverflow',
},
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select id="ddSite" name="ddSite" v-model="ddSite">
<option :value="null">-- Select a Site --</option>
<option v-for="option in sites" :value="option.SiteId">
{{ option.SiteName }}
</option>
</select>
</div>

How to get index data from object used in v-for in select

I have a component involving a select element. Below, opts is an array of objects.
Vue.component('atcf-select', {
props: [
'opts',
],
data() {
return {
element_index: '',
};
},
template: `
<div>
<select #change="onChange(opt,index)">
<option v-for="(opt,index) in opts">
{{ opt.text }} {{opt.index}}
</option>
</select>
</div>
`,
methods: {
onChange(opt,index) {
//Do something with opt and index...
}
}
};
The problem is obviously I cannot get the selected opt object and its index, and use it as a parameter for onChange method. What is the correct way to get the selected option's index and object?
You won't be able to pass the opt or index values to the change listener on the select element because it is outside the scope of the v-for.
If you don't specify any parameters for the onChange handler, Vue will implicitly pass an event object. From there, you can get the selectedIndex value via e.target.selectedIndex.
Here's an example:
new Vue({
el: '#app',
data() {
return {
opts: [
{ value: 'a', text: 'A' },
{ value: 'b', text: 'B' },
{ value: 'c', text: 'C' },
]
}
},
methods: {
onChange(e) {
let index = e.target.selectedIndex;
let option = this.opts[index];
console.log(index, option);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.8/vue.min.js"></script>
<div id="app">
<select #change="onChange">
<option v-for="(opt, index) in opts" :key="index" :value="opt.value">
{{ opt.text }}
</option>
</select>
</div>
You can use v-model
{{ option.value }} - {{ option.text }}
Index of {{valeureSelectionnee}} is : {{ IndexValeureSelectionnee }}