VueJS how to update data on selection - javascript

In a VueJS 2.0 I want to update the rendering of items using a v-for directive when a selection changes.
html:
<main>
{{ testvalue }}
<select v-model="selected.name">
<option v-for="foo in foobar">{{foo.name}}</option>
</select>
<span>Selected: {{ selected.name }}</span>
<div v-for="(value, key) in selected.properties">
<p>{{ key }} {{ value }}</p>
</div>
</main>
app.js
new Vue({
el: 'main',
data: {
foobar: [
{ name: 'rex', type: 'dog', properties: [{color: 'red', sound: 'load'}] },
{ name: 'tike', type: 'cat', properties: [{color: 'brown', sound: 'quiet'}] },
{ name: 'tiny', type, 'mouse', properties: [{color: 'white', sound: 'quiet'}]}
],
selected: { name: 'tiny', type, 'mouse', properties: [{color: 'white', sound: 'quiet'}]},
testvalue: 'Test'
},
created: function () {
this.selected = this.foobar[0];
},
mounted: function () {
this.selected = this.foobar[1];
}
})
jsfiddle here: https://jsfiddle.net/doritonimo/u1n8x97e/
The v-for directive does not update when the selected object it is getting it's data from changes. Is there a way to tell the v-for loop to update when data changes in Vue?

You fiddle still contains some typo so it doesn't work.
Please check: https://jsfiddle.net/u1n8x97e/39/
You don't need to store the entire selected object. You can just keep the index.
<select v-model="selected">
<option v-for="(foo, i) in foobar" :value="i">{{foo.name}}</option>
</select>
Now selected is just a number:
selected: 0
And you access the selected object by foobar[selected]

Related

Vuetify v-select + item-disabled how to use it?

at sample of
https://vuetifyjs.com/en/components/selects/#multiple
<v-select
v-model="value"
:items="items"
multiple
item-disabled=['foo','fizz'] //read only not work?
></v-select>
<script>
export default {
data: () => ({
items: ['foo', 'bar', 'fizz', 'buzz'],
value: ['foo', 'bar', 'fizz', 'buzz'],
}),
}
</script>
As mentioned in the Vuetify documentation, your items can be an array of objects with the following properties:
{
text: string | number | object,
value: string | number | object,
disabled: boolean,
divider: boolean,
header: string
}
Your example becomes:
<template>
<v-select
v-model="value"
:items="items"
multiple
></v-select>
</template>
<script>
export default {
data: () => ({
items: [
{
text: "foo",
value: "foo",
disabled: true,
},
{
text: "bar",
value: "bar",
},
{
text: "fizz",
value: "fizz",
disabled: true,
},
{
text: "buzz",
value: "buzz",
},
],
}),
};
</script>
As per the github issue raised here [Which is still open]: https://github.com/vuetifyjs/vuetify/issues/5557
If an array is passed it's used as a path to a property (['a', 'b'] is
'a.b'), not a list of item values.
So as per now, we cannot pass array directly to item-disabled to make some options disabled.
As mentioned in above answer,
Your current array needs to be converted to array of objects in order for
item-disabled to work. We need to pass array of objects with disabled:true for the objects that needs to be disabled.
[
{text: 'Bar', value: 'Bar'},
{text: 'Gizz - Disabled', value: 'Gizz', disabled: true}
]
Here is the example - https://codepen.io/akshayd21/pen/qBqGONz
Similar questions for reference:
How can I disable literal values in Vuetify?
v-select deactivate some items/options

Multiple Checkbox selected elements pass to array and from another array show selected as checked in vue js

Am very new to vue js and need a way where I have multiple checkboxes and when I select them an array gets updated with the checked elements with Vue JS.
Eg :
allcolors = ['Red', 'Blue', 'Green'];
and I select first two so my
selectedColors = ['Red', 'Blue'];
and then click saves, saves it to database.
When I open the form Red and Blue gets checked fetching record from database.
fetchedColors = ['Red', 'Blue'];
new Vue({
el: "#app",
data: {
items: [
{ label: 'Red', value: 'red' },
{ label: 'Blue', value: 'blue' },
{ label: 'Green', value: 'green' },
],
checkedValues: [],
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label
v-for="(item, index) in items"
:key="index"
>
{{ item.label }}
<input
type="checkbox"
:value="item.value"
v-model="checkedValues"
/>
</label>
{{ checkedValues }}
</div>
Not really sure what you're asking. Do you mean something like this? Check the docs they may help - https://v2.vuejs.org/v2/guide/forms.html#Checkbox
new Vue({
el: "#app",
data: {
items: [
{ label: 'Red', checked: true },
{ label: 'Blue', checked: true },
{ label: 'Green', checked: false },
],
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<label
v-for="(item, index) in items"
:key="index"
>
{{ item.label }}
<input
type="checkbox"
:checked="item.checked"
#change="({ target: { checked }}) => items[index].checked = checked"
/>
</label>
</div>
If you want to show checkboxes that are checked when the form displays you could do something like this.

VueJS 2: cannot set two-way data-binding for input components

Being quite new to Vue, I ran into the issue when I cannot establish binding between input/select tags inside components and the data inside Vue instance.
Example #1:
html
<sidebar-select
:title="UI.sidebar.localeSelect.title"
:name="UI.sidebar.localeSelect.name"
:options="UI.sidebar.localeSelect.options"
:vmodel="selectedLocale">
</sidebar-select>
<sidebar-select
:title="UI.sidebar.currencySelect.title"
:name="UI.sidebar.currencySelect.name"
:options="UI.sidebar.currencySelect.options"
:vmodel="state.currency">
</sidebar-select>
js - component
Vue.component('sidebar-select', {
props: ['title', 'name', 'options', 'vmodel'],
data() {
return {
vmodel: this.value
}
},
template: `<div class="col-xs-12 col-md-6" style="padding-left:0;padding-right:30px">
<div class="cg">
<label :for="name"><h4>{{ title }}</h4></label>
<select class="form-control form-horizontal" style="max-width: 300px"
:name="name"
v-model="vmodel">
<option v-for="option in options" :value="option.value">{{ option.text }}</option>
</select>
</div>
</div>`
});
js - data part
var app = new Vue({
el: '#app',
data: {
selectedLocale: 'ru',
user: {
'ru': {
name: 'Саша',
surname: 'Найдович',
position: 'программист',
phone: '1234567',
email: 'jdlfh#jdlbf.com'
},
'en': {
name: 'Alex',
surname: 'Naidovich',
position: 'frontend',
phone: '1234567',
email: '1234567#email.eu'
}
},
state: {
locale: 'ru',
currency: '€',
/* *** */
},
UI: {
sidebar: {
localeSelect: {
title: 'Язык КП',
name: 'offer-lang',
options: [
{value: 'en', text: 'International - English'},
/* *** */
{value: 'ru', text: 'Русский'}
],
preSelected: 'ru',
stateprop: 'locale'
},
currencySelect: {
title: 'Валюта КП',
name: 'offer-curr',
options: [
{value: '$', text: '$ (Dollar)'},
{value: '€', text: '€ (Euro)'},
{value: '₤', text: '₤ (UK Фунт)'},
{value: '₽', text: '₽ (RUS Рубль)'},
{value: '', text: 'Ввести вручную'}
],
preSelected: '€',
stateprop: 'currency'
},
} /* etc */
}
}
});
There are 2 errors I run into: [Vue warn]: The data property "vmodel" is already declared as a prop. Use prop default value instead. at init and [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "vmodel" vhen I try to change selects. I wish to know what am I doing wrong and what would be the best-practice way for this case.
UPDATE: the main question is about how to properly use v-model two-way-data-binding when passing v-model as an argument into the props of component.
To be updated: example #2 with text inputs will be added tomorrow (the code is left at work).

How to Filter list from multiple select options (dropdowns) using Vuejs

I need to figure out the filter function that will accomplish the filtering of a list of objects based on the selection from multiple dropdown's. If nothing is selected in the dropdown, it shouldn't filter on any of those values.
I have setup a fiddle which lays out a mock structure but need help writing the javascript function(s) to filter the list in realtime when an option is selected from dropdown.
Here is example structure: https://jsfiddle.net/5k4ptmqg/751/
<div id="app">
<select v-model="type">
<option value="type1">Type 1</option>
<option value="type2">Type 2</option>
</select>
<select v-model="size">
<option value="size1">Size 1</option>
<option value="size2">Size 2</option>
</select>
<ul>
<li v-for="item in items">
<span>{{ item.name }}</span>
<span>{{ item.type }}</span>
<span>{{ item.size }}</span>
</li>
</ul>
</div>
new Vue({
el: '#app',
data: {
items: [
{
name: 'name1',
type: 'type1',
size: 'size1'
},
{
name: 'name2',
type: 'type2',
size: 'size2'
},
{
name: 'name3',
type: 'type1',
size: 'size1'
},
{
name: 'name4',
type: 'type2',
size: 'size2'
}
]
}
})
Some issues you had:
v-model="type"/"size" is wrong, it should bind with selectedType/Size. v-model for <select> means the current data for this Dom, not the data of its children.
Create one computed, return filtered result instead of v-for="item in items"
After fixed them, the codes will be like below:
new Vue({
el: '#app',
data: {
selectedType: '',
selectedSize: '',
items: [
{
name: 'name1',
type: 'type1',
size: 'size1'
},
{
name: 'name2',
type: 'type2',
size: 'size2'
},
{
name: 'name3',
type: 'type1',
size: 'size1'
},
{
name: 'name4',
type: 'type2',
size: 'size2'
}
]
},
computed: {
computed_items: function () {
let filterType= this.selectedType,
filterSize = this.selectedSize
return this.items.filter(function(item){
let filtered = true
if(filterType && filterType.length > 0){
filtered = item.type == filterType
}
if(filtered){
if(filterSize && filterSize.length > 0){
filtered = item.size == filterSize
}
}
return filtered
})
}
}
})
<script src="https://unpkg.com/vue#2.0.1/dist/vue.js"></script>
<div id="app">
<select v-model="selectedType">
<option value="type1">Type 1</option>
<option value="type2">Type 2</option>
</select>
<select v-model="selectedSize">
<option value="size1">Size 1</option>
<option value="size2">Size 2</option>
</select>
<ul>
<li v-for="item in computed_items">
<span>{{ item.name }}</span>
<span>{{ item.type }}</span>
<span>{{ item.size }}</span>
</li>
</ul>
</div>

using `filterBy` with dynamic select list

I'm building a form with a long list of select items using vue.js. I'm using the dynamic select list documented here: http://012.vuejs.org/guide/forms.html#Dynamic_Select_Options
However, I want to allow users to quickly filter this list using the filterBy directive. I don't see how you can combine these two-- is it possible to filter a dynamic list? Or can filterBy only be used against a v-for?
In 0.12 you can use filters with the options param. The docs show a syntax that looks identical to filtering v-for.
Here is an example showing filterBy (uses version 0.12.16):
var app = new Vue({
el: '#app',
data: {
selected: '',
options: [
{ text: '1', value: 1, show: true },
{ text: '2', value: 2, show: false },
{ text: '3', value: 3, show: true },
{ text: '4', value: 4, show: true },
{ text: '5', value: 5, show: false },
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.16/vue.js"></script>
<div id="app">
Filter by 'show' <br>
<select v-model="selected" options="options | filterBy true in 'show'"></select>
</div>
Note: the options param for <select v-model> has been deprecated in 1.0. In 1.0, you can use v-for directly within <select>. v-for can be nested to use optgroups.
Check this fiddle https://jsfiddle.net/tronsfey/4zz6zrxv/5/.
<div id="app">
<input type="text" v-model="keyword">
<select name="test" id="test">
<optgroup v-for="group in list | myfilter keyword" label="{{group.label}}">
<option value="{{item.price}}" v-for="item in group.data">{{item.text}}</option>
</optgroup>
</select>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.js"></script>
new Vue({
el: '#app',
data: function () {
return {
keyword : '',
list: [
{
label:'A',
data:[
{price: 3, text: 'aa'},
{price: 2, text: 'bb'}
]
},
{
label:'B',
data:[
{price: 5, text: 'cc'},
{price: 6, text: 'dd'}
]
}
]
}
},
filters : {
myfilter : function(value,keyword){
return (!keyword || keyword === 'aaa') ? value : '';
}
}
})
You can use v-for to create optgroups and then use filterBy or a custom filter instead(as in the fiddle) to filter your options data.
Hope it would help.

Categories

Resources