Vue.js connected data for multiple select option - vue.js

Here is my code
<li>
<select v-model="selectYear" id="search-year" class="w-100 text-center mb-1" name="year" >
<option v-for="year in years" v-bind:value="year.value">
{{ year.text }}
</option>
</select>
</li>
<li>
<select v-model="selectMake" class="w-100 text-center mb-1" name="make">
<option v-for="make in makes" v-bind:value="make.value">
{{ make.text }}
</option>
</select>
</li>
and the components data:
export default {
name: 'search',
data: function () {
return{
selectYear: '2017',
years: [
{ text: '2017', year: '2017' },
{ text: '2016', year: '2016' },
{ text: '2015', year: '2015' }
],
selectMake: '',
makes: [
{ text: 'Sony', value: 'Sony', year: '2017' },
{ text: 'Asus', value: 'Asus', year: '2017' },
{ text: 'IPhone', value: 'IPhone', year: '2016'}
]
}
}
}
What I want
I have multiple select options that is connected in terms of what only to show depending on the previous selected option.
For example
Scenario 1: Year Selected: 2017
Select Make Options Available: ['Sony','Asus']
Scenario 2: Year Selected: 2017
Select Make Options Available: ['Iphone']
Scenario 3: Year Selected: None
Select Make Options Available: []
Is it possible to implement in Vue.js?

this is a typical case where you would use computed values.
add a computed value filteredMakes to filter makes based on selectYear
computed: {
filteredMakes() {
return this.makes.filter((obj, i) => {
return obj.year === this.selectYear
});
}
}
and use the computed value in the v-for for option
<option v-for="make in filteredMakes" v-bind:value="make.value">
filteredMakes will be updated automatically everytime selectYear changes. ain't Vue magical ?

Related

How can i get :key value in v-for loop in a variable?

In Vuejs, how can i get :key value which stores value from v-for loop in a dropdown. I am trying to get id of dropdown along with the name. I can get name using #change>event.target.value but is there any possibility to get key value?
Thanks
<select #change="checkFirst($event)" v-model="firstDropdownValue">
<option value="none" selected="selected"> Select one...</option>
<option
v-for="data in getCategoriesDetail"
:key="data.id" :
:value="data.name">{{data.name}}</option>
</select>
As per my understanding, You want to get the value of :key which is data.id of the selected option from the dropdown. If Yes, You can use v-model to get the whole object instead of just name and then you can filtered out the properties you want in the script.
Demo :
new Vue({
el: '#app',
data: {
getCategoriesDetail: [{
id: 1,
name: 'Option 1'
}, {
id: 2,
name: 'Option 2'
}, {
id: 3,
name: 'Option 3'
}, {
id: 4,
name: 'Option 4'
}],
firstDropdownValue: 'none'
},
methods: {
checkFirst() {
console.log('id : ' + this.firstDropdownValue.id)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select #change="checkFirst" v-model="firstDropdownValue">
<option value="none">Select one...</option>
<option
v-for="item in getCategoriesDetail"
:key="item.id"
:value="item">{{ item.name }}</option>
</select>
</div>
You can simply use the v-model you use in your select !
And you should use the entire object in the :value instead of just the name :value="data" and then use it in the template as firstDropdownValue.name
new Vue({
el: "#app",
data: () => ({
firstDropdownValue: null,
getCategoriesDetail: [
{id:1, name: "foo"},
{id:2, name: "bar"},
{id:3, name: "baz"},
]
}),
methods: {
checkFirst(){
console.log(this.firstDropdownValue)
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select #change="checkFirst" v-model="firstDropdownValue">
<option value="none" selected="selected"> Select one...</option>
<option
v-for="data in getCategoriesDetail"
:key="data.id"
:value="data"
>{{data.name}}</option>
</select>
Selected value : {{firstDropdownValue && firstDropdownValue.name}}
</div>

Remove certain items from the select drop-down menu using VueJS

I'm displaying 3 drop-down menus. Depending on what subject is chosen in the select menu one affects the subjects that should display in the other 2 select menus.
For example, if "Economics" is selected in drop-down one then "Marketing" and "Mathematics" should not display in the other menus. There are 7 different scenarios to cover in total, similar to this one. Can anyone help me get off the ground with this, please?
<template>
<select v-model="one">
<option v-for="subject in subjects">
{{ subject }}
</option>
</select>
<select v-model="two" :disabled="!one">
<option v-for="subject in subjects.filter(item => item.split(' ')[0].indexOf(this.one.split(' ')[0]))">
{{ subject }}
</option>
</select>
<select v-model="three" :disabled="!two">
<option v-for="subject in subjects.filter(item => item.split(' ')[0].indexOf(this.one.split(' ')[0]) && item.split(' ')[0].indexOf(this.two.split(' ')[0]))">
{{ subject }}
</option>
</select>
<div>
Selected: {{one}} {{two}} {{three}}
</div>
</template>
<script>
export default {
data() {
return {
subjects: [
"Education",
"Economics",
"English",
"English & Creative Writing",
"French",
"History",
"Law",
"Marketing",
"Mathematics",
"Psychology",
"Spanish"
],
one: "",
two: "",
three: "",
}
}
}
</script>
The general idea is to map up the relation between what I would call "top level subjects" or topics and the "sub level subjects" or sub-topics.
If you know you only ever will have three inputs (at max), then doing a mapping for a pre-populated array is ok. However, if you're looking at dynamically adding more levels, you would need to put down more work. That being said, I've looked at this briefly and added a subject <-> topic relation. Each entry has the parent attribute which defines if they have one or more. If they don't, they're a "top level subject" or topic. If they do, they're a sub-topic.
By handling the onChange event for each select, you can figure out what ID the subject you selected has and find the corresponding entry in the subjects object array. Once you found that, you filter all entries that have parents !== null and match every ID in their parent array. This is calculated using a property, which is ideal for such purposes.
HTML
<div id="app">
<select
v-model="selected[0].id"
#change="selectTopic($event)"
>
<!-- List first only the top level topics -->
<option
v-for="(subject, subjectKey) in topics"
:key="`subject-${subjectKey}`"
:value="subject.id"
>
{{ subject.name }}
</option>
</select>
<select
v-if="nextLevelSubjects"
v-model="selected[1].id"
#change="selectTopic($event)"
>
<!-- List first only the top level topics -->
<option
v-for="(subject, subjectKey) in nextLevelSubjects"
:key="`next-level-subject-${subjectKey}`"
:value="subject.id"
>
{{ subject.name }}
</option>
</select>
<div v-if="someSelectionHasBeenMade">
<pre>
All topics selected: {{ selected }}
</pre>
</div>
</div>
Vue Code (Excerpt)
data: {
someSelectionHasBeenMade: false,
nextLevelSubjects: null,
selected: [
{
id: null
},
{
id: null
},
{
id: null
}
],
subjects: [
{
id: 1,
name: "Education",
parent: null
},
{
id: 2,
name: "English",
parent: [1]
},
{
id: 3,
name: "English & Creative Writing",
parent: [1]
},
{
id: 4,
name: "French",
parent: [1]
},
{
id: 5,
name: "Economics",
parent: null
},
{
id: 6,
name: "Law",
parent: [5]
},
{
id: 7,
name: "Marketing",
parent: [5]
},
]
},
computed: {
topics () {
return this.subjects.filter(e => e.parent === null)
}
},
methods: {
selectTopic (event) {
this.someSelectionHasBeenMade = true
const parentId = Number.parseFloat(event.target.value)
this.nextLevelSubjects = this.subjects.filter(e => e.parent !== null).filter(i => i.parent.every(p => p === parentId))
}
}
})
I've made a JSFiddle here: https://jsfiddle.net/Coreus/md7ktj6e/2/
Making a sub-topic be parent to several topics
If you want a sub-topic to match either one of more subjects / topics, put in several IDs in the parent property for the sub-topic in question and change the filtering by parent to some. Like so:
subjects: [
{
id: 1,
name: "Education",
parent: null
},
{
id: 2,
name: "Languages",
parent: null
},
{
id: 3,
name: "English",
parent: [1, 2]
},
....
{
id: 4,
name: "French",
parent: [1, 2]
},
{
id: 5,
name: "History",
parent: [1]
},
By the example above, the relation tree looks like so:
Education
English
French
History
Languages
English
French
Then change the filtering to use some instead of every.
this.nextLevelSubjects = this.subjects.filter(e => e.parent !== null).filter(i => i.parent.some(p => p === parentId))
Edit: Code example has been updated
Please note this just illustrates purpose. You obviously need to put down more work for it to work on additional tiers (sub-topics) down the line. It should, however, give you an idea on how to approach this further.

Angular 8 how to pass current object and its index in change event

<pre>
<select (change)="getSelecteItem()">
<option *ngFor="let item of sampleDropDown">
{{item.value}}
</option>
</select>
<pre>
public sampleDropDown =
[{ id: '1', value: 'Test0' }, { id: '2', value: 'Test1' }, { id: '1', value: 'Test2' }];
getSelecteItem() {
}
</code>
I am binding dropdown using Angular 8 with *ngFor..
1) I want to pass current selected option in change event
2) I want to pass current selected option index in change event
you can do that by accessing the special variable $event.
In your template (HTML file)
<select (change)="getSelecteItem($event)">
<option *ngFor="let item of sampleDropDown">
{{ item.value }}
</option>
</select>
In your component:
getSelecteItem(event) {
const value = event.target.value;
console.log(value); //// test0, test1, etc...
}
<select (change)="getSelecteItem($event)">
<option *ngFor="let item of sampleDropDown" value="{{item.id}}" >
{{item.value}}
</option>
</select>
public sampleDropDown =
[{ id: '1', value: 'Test0' }, { id: '2', value: 'Test1' }, { id: '1', value: 'Test2' }];
getSelecteItem(event) {
event.currentTarget.options.selectedIndex
event.currentTarget.options[event.currentTarget.options.selectedIndex].text
event.currentTarget.options[event.currentTarget.options.selectedIndex].value
}

Add element in option

I'm creating this post because I'm trying to add and remove option in an HTML select from a function.
I've searched everywhere but unfortunately I didn't find anything.
thank you in advance for your help!
methods: {
addElement() {
// function add option in actions select
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<template>
<div class="col-md-10 col-md-offset-1">
<select name="actions" v-model="model.actions" class="form-control">
</select>
</div>
</template>
Example from the vue docs https://v2.vuejs.org/v2/guide/forms.html#Select (find using v-for with select at that page):
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
If you want to add option to select just create some method addOption(option):
methods:{
addOption(option){
this.options.push(option);
}
}

V-model for select component

In Vue we can bind data on two way in the select component like below:
<select v-model="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
Our Vue code is:
new Vue({
el: '...',
data: {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
})
Here v-model property works for the value of the option.
Is there any method for the same thing to the text property of the option.
In other words, is there any method works with One,Two and Three values.