1π
β
In my opinion, your computed idea seems to be the best one according to your problem.
Note : that I added a clear of the subcountry if the value of the country is changed.
Example
new Vue({
el: '#app',
vuetify: new Vuetify(),
computed: {
subCountryItemsFiltered() {
return this.subCountry.filter(subCountry => subCountry.country === this.countrySelected)
}
},
data() {
return {
country: ['france', 'spain', 'uk'],
countrySelected: null,
subCountry: [
{value: 'Alsace', country: 'france'},
{value: 'Catalogne', country: 'spain'},
{value: 'Greater London', country: 'uk'},
],
subCountrySelected: null
}
},
})
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/vuetify@2.3.4/dist/vuetify.min.css'>
<script src='https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js'></script>
<script src='https://cdn.jsdelivr.net/npm/vuetify@2.3.4/dist/vuetify.min.js'></script>
<div id="app" data-app>
<v-select :items="country" v-model="countrySelected" @change="subCountrySelected = null"></v-select>
<v-select
:items="subCountryItemsFiltered"
v-model="subCountrySelected"
item-text="value"
></v-select>
</div>
π€RenaudC5
2π
Considering the following data:
data: () => ({
places: [
{ value: 'Alsace', country: 'Spain' },
{ value: 'Lorraine', country: 'France'},
{ value: 'Greater London', country: 'England'},
{ value: 'Andalousie', country: 'Spain' },
{ value: 'Catalogne', country: 'Spain' }
]
})
You can extract the countries with this computed:
countries() {
return [ ...new Set(this.places.map(p => p.country))]
}
And you can get the available places for the current country using another computed:
availablePlaces() {
return this.places
.filter(p => p.country === selectedCountry)
.map(p => p.value)
}
Example, using Options API:
const { createApp, defineComponent } = Vue;
const App = defineComponent({
template: '#app-tpl',
data: () => ({
places: [
{ value: 'Alsace', country: 'France' },
{ value: 'Lorraine', country: 'France'},
{ value: 'Greater London', country: 'England'},
{ value: 'Andalousie', country: 'Spain' },
{ value: 'Catalogne', country: 'Spain' }
],
selectedCountry: '',
selectedPlace: ''
}),
computed: {
countries() {
return [...new Set(this.places.map(p => p.country))]
},
availablePlaces() {
return this.places
.filter(p => p.country === this.selectedCountry)
.map(p => p.value)
}
},
watch: {
selectedCountry() {
// reset selectedPlace when changing the country
if (!this.availablePlaces.includes(this.selectedPlace)) {
this.selectedPlace = ''
}
}
}
});
createApp(App).mount('#app');
<script src="https://unpkg.com/vue@3.2/dist/vue.global.prod.js"></script>
<div id="app"></div>
<template id="app-tpl">
<select v-model="selectedCountry">
<option></option>
<option v-for="country in countries"
:key="country"
v-text="country"></option>
</select>
<select v-model="selectedPlace">
<option></option>
<option v-for="place in availablePlaces"
:key="place"
v-text="place"></option>
</select>
<pre
v-text="JSON.stringify({selectedCountry, selectedPlace, availablePlaces }, null, 2)"></pre>
</template>
Same example, with Composition API:
const { createApp, reactive, computed, toRefs, watchEffect, defineComponent } = Vue;
const places = [
{ value: 'Alsace', country: 'France' },
{ value: 'Lorraine', country: 'France'},
{ value: 'Greater London', country: 'England'},
{ value: 'Andalousie', country: 'Spain' },
{ value: 'Catalogne', country: 'Spain' }
];
const App = defineComponent({
template: '#app-tpl',
setup() {
const state = reactive({
selectedCountry: '',
selectedPlace: '',
countries: [...new Set(places.map(p => p.country))],
availablePlaces: computed(() => places
.filter(p => p.country === state.selectedCountry)
.map(p => p.value)
)
});
watchEffect(() => {
if (!state.availablePlaces.includes(state.selectedPlace)) {
state.selectedPlace = ''
}
})
return { ...toRefs(state) }
}
})
createApp(App).mount('#app')
<script src="https://unpkg.com/vue@3.2/dist/vue.global.prod.js"></script>
<div id="app"></div>
<template id="app-tpl">
<select v-model="selectedCountry">
<option></option>
<option v-for="country in countries" :key="country">{{country}}</option>
</select>
<select v-model="selectedPlace">
<option></option>
<option v-for="place in availablePlaces" :key="place">{{place}}</option>
</select>
<pre v-text="JSON.stringify({selectedCountry, selectedPlace, availablePlaces }, null, 2)"></pre>
</template>
π€tao
Source:stackexchange.com