Dynamically change select input options in vuejs 2 - javascript

How to change dynamically the options in a select dropdown v-model ?
I have 2 select inputs, one should change according to the others.
For example, if i select "fruits" the select display the fruits, if i select "vegetables" it displays the vegetables.

I don't use Vuejs, but after looking at the documentation:
var TypesArr = {
Fruit: [{ text: 'Apple', value: 'Apple' }, { text: 'Orange', value: 'Orange' }, { text: 'Mango', value: 'Mango' }],
Meat: [{ text: 'Steak', value: 'Steak' }, { text: 'Pork', value: 'Pork' }]
}
var selectTwo = new Vue({
el: '#select2',
data: {
selected: TypesArr['Fruit'][0],
options: TypesArr['Fruit']
},
methods: {
update: function (value)
{
this.options = TypesArr[value]
}
}
})
new Vue({
el: '#select1',
data: {
selected: 'Fruit',
options: [ { text: 'Fruit', value: 'Fruit' }, { text: 'Meat', value: 'Meat' } ]
},
methods: {
onChange: function (event)
{
selectTwo.update(event.srcElement.value)
}
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<select v-on:change="onChange" id="select1">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<select id="select2">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>

The other answers are not really 'Vue' answers.
How you handle this depends on what you want to do with the select box. I'm assuming you'll to handle the input on a form.
Two options:
Use a Computed property
Use v-if to show different select boxes. This would be ideal if each select box has a different v-model
Computed Property
<template>
<div class="container">
<select id="firstInput" v-model="selected">
<option v-for="option in firstInputOptions" :value="option">
{{ option }}
</option>
</select>
<select id="secondInput" v-model="secondInputSelected">
<option v-for="option in secondInputOptions" :value="option">
{{ option }}
</option>
</select>
</div> <!-- /container -->
</template>
<script>
export default {
computed: {
secondInputOptions(){
return this.selected === 'fruit' ? this.fruit : this.vegetables
}
},
data () {
return {
fruit: ['apple', 'banana', 'orange'],
vegetables: ['carrot', 'beet', 'celery'],
firstInputOptions: ['fruit', 'vegetables']
selected: 'fruit',
secondInputSelected: ''
}
},
}
</script>
Conditional Rendering
<template>
<div class="container">
<select id="firstInput" v-model="selected">
<option v-for="option in firstInputOptions" :value="option">
{{ option }}
</option>
</select>
<select id="secondInputFruit" v-model="selected" v-if="selected == 'fruit'">
<option v-for="option in secondInputOptions" :value="option">
{{ option }}
</option>
</select>
<select id="secondInputVegetables" v-model="vegetableSelected" v-else-if="selected == 'vegetables'">
<option v-for="option in secondInputOptions" :value="option">
{{ option }}
</option>
</select>
</div> <!-- /container -->
</template>
<script>
export default {
data () {
return {
fruits: ['apple', 'banana', 'orange'],
fruitSelected: '',
vegetables: ['carrot', 'beet', 'celery'],
vegetableSelected: '',
firstInputOptions: ['fruit', 'vegetables']
selected: 'fruit'
}
},
}
</script>

Using pure javascript
var typesArr = {fruit: ['Apple', 'Orange', 'Mango'], meat: ['Steak', 'Pork']}
function changeContext(value)
{
if (typesArr.hasOwnProperty(value)) {
var out = ''
for (var i = 0; i < typesArr[value].length; i++) {
out += '<option value="' + typesArr[value][i] + '">' + typesArr[value][i] + '</option>'
}
document.getElementById('select2').innerHTML = out
}
}
changeContext('fruit')
<select onchange="changeContext(this.value)">
<option value="fruit">Fruit</option>
<option value="meat">Meat</option>
</select>
<select id="select2"></select>

Related

Vue JS set first item in a populated select to be selected with v-model

I have tricky challenge with vuejs, I want to have two select fields. the first one should select fruits for example, and the second should list all fruits. If I select vegetable from the first select field, the second select field should list all vegetable.
I stumble and find similar stuff online but I don't know how to make first item in the second select field selected.
anytime I select fruits, the first item on the list in second select first should be selected as default, and if I select vegetable, the first item in the second select field should be selected as default.
pls help me check the code here: https://jsfiddle.net/aj6g87dh/1/
new Vue({
el: '#test',
data: {
category: 'fruits',
list: '',
optionsData: {
fruits: [
{ text: 'Orange', value: 'orange' },
{ text: 'Banane', value: 'banana' },
],
vegetables: [
{ text: 'Brocolis', value: 'brocolis' },
{ text: 'Radish', value: 'radish' },
]
}
},
computed: {
options: function() {
let options = ''
switch (this.category) {
case 'fruits':
options = this.optionsData.fruits
break;
case 'vegetables':
options = this.optionsData.vegetables
break;
default:
options = this.optionsData.fruits
}
return options
}
},
methods: {
onChange: function() {
this.options = this.options
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.5/vue.js"></script>
<div id="test">
<select v-model="category" v-on:change="onChange" id="select1">
<option value="fruits">Fruits</option>
<option value="vegetables">Vegetables</option>
</select>
<select id="select2" v-model="list">
<option v-for="option in options" v-bind:value="option.value"> {{ option.text }} </option>
</select>
<span>{{ }}</span>
</div>
You can remove onChange method and add a watch property. This way you can handle changing logic there.
Also, you can simplify options retrieval to one line.
new Vue({
el: '#test',
data: {
category: 'fruits',
list: '',
optionsData: {
fruits: [{
text: 'Orange',
value: 'orange'
},
{
text: 'Banane',
value: 'banana'
},
],
vegetables: [{
text: 'Brocolis',
value: 'brocolis'
},
{
text: 'Radish',
value: 'radish'
},
]
}
},
computed: {
options: function() {
return this.optionsData[this.category]
}
},
watch: {
category: {
handler: function(newVal) {
this.list = this.optionsData[newVal][0].value;
},
immediate: true
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="test">
<select v-model="category" id="select1">
<option value="fruits">Fruits</option>
<option value="vegetables">Vegetables</option>
</select>
<select id="select2" v-model="list">
<option v-for="(option, i) in options" v-bind:value="option.value"> {{ option.text }} </option>
</select>
<span>{{ }}</span>
</div>

Getting item properties from a dropdown in Vue.Js

I am struggling to output one of the object properties (SKU) from an item selected in a dropdown box. I have tried a few variants with no success.
How can I access one of the object properties if I don't display it (use an expression) in the dropdown. In essence, how do I show the SKU of an item outside of the dropdown?
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
<p>The SKU of your selected item is {{ selected.sku }}</p>
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A', sku:'TT5' },
{ text: 'Two', value: 'B', sku:'BB8' },
{ text: 'Three', value: 'C', sku:'AA9' }
]
}
})
Try to bind the whole object to your option element as follows :
<option v-for="option in options" v-bind:value="option">
by this way you could access its properties like :
<span>Selected: {{ selected.value }}</span>
<p>The SKU of your selected item is {{ selected.sku }}</p>
Since you need the value property to be passed to the backend you could use a computed property to get the selected the object based on the selected value :
Vue.config.devtools = false;
Vue.config.productionTip = false;
new Vue({
el: '#app',
data: {
selectedVal: 'A',
options: [{
text: 'One',
value: 'A',
sku: 'TT5'
},
{
text: 'Two',
value: 'B',
sku: 'BB8'
},
{
text: 'Three',
value: 'C',
sku: 'AA9'
}
]
},
computed: {
selected() {
return this.options.find(op => {
return op.value == this.selectedVal
})
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<select v-model="selectedVal">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<br/>
<span>Selected: {{ selected }}</span>
<p>The SKU of your selected item is {{ selected.sku }}</p>
</div>

How to set optgroup select label in Vue.js?

I'm trying to make a select group in Vue.
Fiddle: https://jsfiddle.net/Tropicalista/vwjxc5dq/
I've tried this:
<optgroup v-for="option in options" v-bind:label="option">
<option v-for="sub in option" v-bind:value="option.value">
{{ sub.text }}
</option>
</optgroup>
My data:
data: {
selected: 'A',
options: {
First: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' }
],
Second: [
{ text: 'Three', value: 'C' }
]
}
}
You are binding the label attribute to option, which is an array. What you want is to bind to the object's key.
You can get the key of each option by specifying a second parameter in the v-for directive:
<optgroup v-for="(option, key) in options" v-bind:label="key">
I'd also rename your options property to optionGroups to avoid further confusion:
data: {
selected: 'A',
optionGroups: {
First: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' }
],
Second: [
{ text: 'Three', value: 'C' }
]
}
}
That way, the template will make more sense:
<optgroup v-for="(group, name) in optionGroups" :label="name">
<option v-for="option in group" :value="option.value">
{{ option.text }}
</option>
</optgroup>
according to above answer. I improve optgroup tag by adding label in optgroup tag
<optgroup v-for="(group, name) in optionGroups" :key="name" :label="`${name}`">
<option v-for="option in group" :key="option.value">
{{ option.text }}
</option>
</optgroup>

Vue js populate new selects when changing the main one

I need your help about populating or loading new select with vue js, I know how to do this with jquery but in vue i don't know how because i'm new with this library.
i have the main select :
<select>
<option value='3'>FRANCE</option>
<option value='5'>USA</option>
<option value='6'>CANADA</option>
<option value='8'>MOROCCO</option>
</select>
I want that if i choose FRANCE i get a select of FRANCE cities from database, and also when i select USA i get an other select of USA cities from database.
So for example i will get :
<select>
<option value='6'>CANADA</option>
<option value='8'>MOROCCO</option>
</select>
<select>
<option value='34'>France city one</option>
<option value='35'>France city two</option>
</select>
<select>
<option value='3'>Usa city one</option>
<option value='5'>Usa city two</option>
</select>
When choosing France and USA i will populate select of cities with an array
I appreciate any help, I don't realy know how can i do this with vue js,
I don't want add all select of cities in my html because i don't know how much countries i have.
I tried this but this not resolve my probleme :
const addProduct = new Vue({
el: '#addProduct',
data: {
name: '',
name_url: '',
cities: '',
countries: [],
range: 0
},
created: function () {
this.$http.get('/api/countries').then(response => {
this.countries = response.data
}, response => {
});
},
methods: {
addForm: function(val, data) {
this.range += 1;
alert(this.range)
var index = _.findIndex(this.countries,{city_id: val});
this.countries.splice(index, 1)
}
},
watch: {
'cities' (val, oldVal) {
this.$http.post('/api/cities/values', {city_id:val}).then(response => {
this.addForm(val, response.data);
}, response => {
});
}
}
});
in html :
<div class="uk-grid" data-uk-grid-margin>
<div class="uk-width-medium-1-4">
<label for="attribute">Countries</label>
<md-select name="country" id="country" v-model="country">
<md-option v-for="country in countries" :value="country.country_id">#{{ country.name }}</md-option>
</md-select>
</div>
</div>
<div class="uk-grid" data-uk-grid-margin>
<my-cities v-for="n in range"></my-cities>
</div>
<script type="x-template" id="my-cities">
<div class="uk-width-medium-1-4">
<label for="attr">Cities</label>
<md-select name="attr" id="attr" v-model="attr">
<md-option value="">Select </md-option>
<md-option value="val in values">Select</md-option>
</md-select>
</div>
</script>
an example like this on Jsfiddle : http://jsfiddle.net/pu8pp62v/3/
This is an example that you can maybe use (but need some modifications to use your API call) :
new Vue({
el: "#app",
data: function() {
return {
selectedCountries: [],
selectOptionsCountries: [
{ value: 3, name: 'FRANCE' },
{ value: 5, name: 'USA' },
{ value: 6, name: 'CANADA' },
{ value: 8, name: 'MOROCCO' }
],
selectedCities: [],
selectOptionsCities: []
}
},
methods: {
},
watch: {
selectedCountries: function(newValue, oldValue) {
this.selectOptionsCities = [];
this.selectedCities = [];
for( var i = 0, length = newValue.length; i < length; i++ ){
this.selectedCities[i] = [];
if( newValue[i] === 3 ){
this.selectOptionsCities.push(
[{ value: 31, name: 'Paris' },
{ value: 32, name: 'Marseille' }]
)
}
if( newValue[i] === 5 ){
this.selectOptionsCities.push(
[{ value: 51, name: 'New-York' },
{ value: 52, name: 'Boston' }]
)
}
if( newValue[i] === 6 ){
this.selectOptionsCities.push(
[{ value: 61, name: 'Montreal' },
{ value: 62, name: 'Vancouver' },
{ value: 63, name: 'Ottawa' },
{ value: 64, name: 'Toronto' }]
)
}
if( newValue[i] === 8 ){
this.selectOptionsCities.push(
[{ value: 81, name: 'Rabat' },
{ value: 82, name: 'Casablanca' },
{ value: 83, name: 'Fes' }]
)
}
}
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.5/vue.js"></script>
<div id="app">
Selected countries : {{ selectedCountries }}
<br />
Selected cities : {{ selectedCities }}
<br />
<select v-model="selectedCountries" multiple>
<option v-for="(option, index) in selectOptionsCountries" :value='option.value'>
{{ option.name }}
</option>
</select>
<select v-for="(optionsCities, index) in selectOptionsCities" v-model="selectedCities[index]" multiple>
<option v-for="(option, index) in optionsCities" :value='option.value'>
{{ option.name }}
</option>
</select>
</div>
Added after author's comment:
Check this fiddle: http://jsfiddle.net/jjpfvx5q/1/
Inside 'chosenCities' array you have all selected cities by country (one city per country.)
Original answer:
Here is an example for you: fiddle
Is that what you are trying to achieve?
setTimeout functions are just pretending a real data fetching.
<script src="//unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<template>
<div>
<select v-model="country">
<option disabled value="">Please select one</option>
<option
v-for="c in countries"
:value="c.id">{{ c.name }}</option>
</select>
<span>Selected: {{ country }}</span>
<span v-if="cities.length">Cities:</span>
<ul v-if="cities.length">
<li v-for="c in cities">{{ c }}</li>
</ul>
</div>
</template>
</div>
<script>
var Main = {
data() {
return {
country: {},
countries: [],
cities: [],
coInit: [{ id: '3', name: 'France' }, { id: '2', name: 'USA' }],
cFrance: ['Paris', 'Whatever'],
cUSA: ['NY', 'LA']
}
},
methods: {
loadCountries: function () {
setTimeout(() => { this.countries = this.coInit }, 500);
},
getCities: function() {
if(this.country) {
switch (this.country) {
case '3':
setTimeout(() => { this.cities = this.cFrance }, 500);
break;
case '2':
setTimeout(() => { this.cities = this.cUSA }, 500);
break;
}
}
}
},
mounted() {
this.loadCountries();
},
watch: {
country: function() {
this.getCities();
}
}
}
var Ctor = Vue.extend(Main);
new Ctor().$mount('#app');
</script>

How to use two value on vue.js 2?

I try to my component like this :
<script>
export default {
template: '\
<select class="form-control" v-on:change="search">\
<option v-for="option in options" v-bind:value="'+option.id+'|'+option.name+'">{{ option.name }}</option>\
</select>',
mounted() {
...
},
...
};
</script>
I separate them using separator |
So, I'll be using a split to get the id and the name
I try like that, but there exist error :
Uncaught ReferenceError: option is not defined
How can I solve it?
Here is what you want:
new Vue({
el: '#demo',
data: {
selected: '',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="demo">
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value+'|'+option.text">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>

Categories