Vue.js multiple choice and computed property
I am using Vue.js 2.0 and the Element library.
I want to use multiple choice to attribute some of the roles for my users.
A list of all available roles is accepted and assigned availableRoles
. Since it is an array of an object and v-model
only accepts an array with a value, I need to extract id
from the roles via a computed property computedRoles
.
My user's current roles are accepted and assigned userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}]
.
computedRoles
then equals [1,3]
Selection selection is ok, but I can't change anything (add or remove option from selection)
What's wrong and how to fix it?
http://jsfiddle.net/3ra1jscx/3/
<div id="app">
<template>
<el-select v-model="computedRoles" multiple placeholder="Select">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}]
}
},
computed : {
computedRoles () {
return this.userRoles.map(role => role.id)
}
}
}
source to share
I agree mostly with @ wostex answer, but it doesn't return the property for you userRoles
. Essentially you have to change computedRoles
and userRoles
. userRoles
becomes a computed property and computedRoles
is a data property. In my update, I changed the name computedRoles
to selectedRoles
.
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
selectedRoles:[1,2]
}
},
computed : {
userRoles(){
return this.availableRoles.reduce((selected, role) => {
if (this.selectedRoles.includes(role.id))
selected.push(role);
return selected;
}, [])
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
And here's the fiddle .
source to share
Check the solution: jsfiddle
The caveat here is that computed properties are basically getters. You can define a setter for the computed property, but my approach is more like my opinion.
In short, instead of v-model
for a computed set v-model
for a data property.
Complete code:
<script src="//unpkg.com/vue/dist/vue.js"></script>
<script src="//unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<template>
<el-select v-model="ids" multiple placeholder="Select" @change="logit()">
<el-option v-for="item in availableRoles" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
</div>
var Main = {
data() {
return {
availableRoles: [{
id: 1,
name: 'Admin'
}, {
id: 2,
name: 'Power User'
}, {
id: 3,
name: 'User'
}],
userRoles: [{'id':1, 'name':'Admin'}, {'id':3, 'name':'User'}],
ids: []
}
},
mounted() {
this.ids = this.userRoles.map(role => role.id);
},
methods: {
logit: function() {
console.log(this.ids);
}
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
source to share