Why do I receive subject (object that I want) on first item but MouseEvent from all other subject changes?
<template v-for="subject in subjects">
<select v-model="subject.name" class="form-control" #change="setNote(subject)">
<option v-for="vsub in validSubjects" :value="vsub.id_subject">{{ vsub.name }}</option>
</select>
</template>
This works for me:
var app = new Vue({
el: '#app',
data: {
message: 'Choose a subject: ',
subjects: [{
name: "Maths"
}, {
name: "Science"
}],
validSubjects: [{
id_subject: "1",
name: "Maths"
}, {
id_subject: "2",
name: "Science"
}, {
id_subject: "3",
name: "English"
}]
},
methods: {
setNote(subject) {
console.log(subject);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
{{ message }}
<template v-for="subject in subjects">
<select v-model="subject.name" class="form-control" #change="setNote(subject)">
<option v-for="vsub in validSubjects" :value="vsub.id_subject">{{ vsub.name }}</option>
</select>
</template>
</div>
Related
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>
Try to select from datalist while a data property is updated on a interval.
What is wrong in my code?
http://jsfiddle.net/startflorin/gr6b1h7j/18
Mounted intervals:
setInterval((ctx) => { ctx.notification = "111"; }, 500, this);
setInterval((ctx) => { ctx.notification = "222"; }, 500, this);
Data:
data: {
notification: null,
demoList:[
{
id: 1,
name: "option 1",
},
{
id: 2,
name: "option 2",
},
{
id: 3,
name: "option 3",
},
],
},
My HTML code:
<div>
{{ notification }}
</div>
<input list='demoList' v-on:change="selectSymbolList(target.value)">
<datalist id="demoList">
<option v-for="item in this.demoList" v-bind:value="item.name" v-bind:key="item.id">{{ item.name }}</option>
</datalist>
To cache the rendering of <input> and <datalist> (to isolate them from unrelated changes in the component's template), put them into a component:
Vue.component('demo-list', {
props: ['items'],
template: `<div>
<input list='demoList'>
<datalist id="demoList">
<option v-for="item in items" v-bind:value="item.name" v-bind:key="item.id">{{ item.name }}</option>
</datalist>
</div>`
})
Note this example requires the runtime compiler to compile the template string. Otherwise, render functions would be required instead of template.
Then use the component in your app's template:
<div id="app">
<div>{{ notification }}</div>
<demo-list :items="demoList"></demo-list>
</div>
demo
Inside a v-for loop how can I apply a filter to the text? My inline template:
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id" v-text="item.name | capitalize"></option>
</select>
I get multiple warnings Property or method "capitalize" is not defined on the instance but referenced during render. Even though the filter is defined.
So I presume its some sort of scope issue in the loop? How can this be solved?
As Vue Guide: Filters mentions, Filters are usable in mustache interpolations and v-bind expressions, not including the directives.
For your codes,
Solution 1 will be mustache interpolations.
Vue.filter('global-capitalize', function (value) {
return value.toUpperCase()
})
new Vue({
el: "#app",
data: {
items: [
{ text: "Learn JavaScript", id: 1 },
{ text: "Learn Vue", id: 2 },
{ text: "Play around in JSFiddle", id: 3 },
{ text: "Build something awesome", id: 4 }
]
},
filters: {
capitalize: function (name) {
return name.toUpperCase()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<h2>Todos:</h2>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id">
{{item.text | capitalize}}
</option>
</select>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id">
{{item.text | global-capitalize}}
</option>
</select>
</div>
Another solution is uses computed properties or methods.
new Vue({
el: "#app",
data: {
items: [
{ text: "Learn JavaScript", id: 1 },
{ text: "Learn Vue", id: 2 },
{ text: "Play around in JSFiddle", id: 3 },
{ text: "Build something awesome", id: 4 }
]
},
computed: {
computedItems: function () {
return this.items.map(item => {
return {text: item.text.toUpperCase(), id: item.id}
})
},
},
methods: {
filterFunc: function (name) {
return name.toUpperCase()
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<select>
<option v-for="(item, index) in computedItems" :key="index" :value="item.id" v-text="item.text">
</option>
</select>
<select>
<option v-for="(item, index) in items" :key="index" :value="item.id" v-text="filterFunc(item.text)">
</option>
</select>
</div>
I'm using <datalist> drop-down menu to display group names in our project.
<data-list
ref="groupName"
name="groupName"
label="Groups: "
:options="groupList"
></data-list>
.....
methods:{
groupList(){
return this.$store.getters['Groups/getGroups']
}
}
But this is displayed in my UI:
I actually want the dropdown to display the label field, which is a group name, and I'll get the value of it. The structure of returned value looks like this:
[
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
It seems the bug is in your data-list component. Most likely you have something like this:
<!-- XXX: DON'T DO THIS -->
<option v-for="option in options" :value="option">{{option}}</option>
Vue.component('data-list', {
props: ['label', 'options'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="mydata">
<datalist id="mydata">
<!-- XXX: DON'T DO THIS -->
<option v-for="option in options" :value="option">
{{option}}
</option>
</datalist>
</div>`,
});
new Vue({
el: '#app',
data() {
return {
groupList: [
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
};
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<data-list label="Groups: " :options="groupList"></data-list>
</div>
But you actually need to set the value of <option> to option.value and its inner text to {{option.label}} (matching your item's data structure):
<option v-for="option in options" :value="option.value">{{option.label}}</option>
Vue.component('data-list', {
props: ['label', 'options'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="mydata">
<datalist id="mydata">
<option v-for="option in options" :value="option.value">
{{option.label}}
</option>
</datalist>
</div>`,
});
new Vue({
el: '#app',
data() {
return {
groupList: [
{label: "test", value: 14},
{label: "Test1", value: 16},
{label: "Test2", value: 17},
{label: "Test3", value: 18},
]
};
}
})
<script src="https://unpkg.com/vue#2.5.17"></script>
<div id="app">
<data-list label="Groups: " :options="groupList"></data-list>
</div>
you can to use like this in html and js.
actually following code is not a component.
sample HTML code
<datalist id="browsers">
<option v-for="lst in groupList" v-bind:value="lst">{{lst.label}}</option>
</datalist>
sample Vue.js code
data:{
groupObj: {},
groupList: []
},
methods:{
groupList(){
this.groupList = this.$store.getters['Groups/getGroups'];
},
},
mounted(){
this.groupList();
}
I understand the question as "How to work with objects in datalists in vue.js"
what are datalists?
datalists provides just templates to fill other controls.
mostly used with text input to provide combobox functionallity (allow also new content to be selected)
At this time implementation in browsers vary greatly, so better to just rely on basic label rendering (don't use value, since browsers handle it differently)
using it in vue with objects
Idea is to use strings and check on every input change if we have a perfect match. Using :value will show the id in chrome, which is probably not what you want. This doesn't work with same-named labels, but then again, such an input makes little sense in that case.
Vue.component('test-data-list', {
props: ['label', 'options', 'value'],
template: `
<div>
<label for="myinput">{{label}}</label>
<input id="myinput" list="data" #change="change" :value="getValue">
<datalist id="data">
<option v-for="option in options">
{{option.label}}
</option>
</datalist>
</div>`,
computed: {
getValue() {
return this.value ? this.value.label : '';
}
},
methods: {
change(e) {
let value = e.currentTarget.value;
if (value) {
let sel = this.options.filter(c => c.label == value);
if (sel.length == 1) {
this.selection = sel[0];
} else {
this.selection = {
label: value,
isNew: true
}
}
} else {
this.selection = undefined;
}
this.$emit('input', this.selection)
}
}
});
new Vue({
el: '#app',
data() {
return {
result: undefined,
groupList: [{
label: "something",
id: 1
},
{
label: "this too",
id: 2
},
{
label: "something different",
id: 3
}
]
};
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
Selected:
<span v-if="result">
"{{ result.label }}"
<span v-if="result.isNew">New!</span>
<span v-else> old object with id:{{result.id}}</span>
</span>
<span v-else>nothing</span>
</div>
<test-data-list label="Select" :options="groupList" v-model="result"></test-data-list>
</div>
I'm new to vue and have a problem with a conditonal rendering (v-if) in an option element.
when i have an empty array i would like to show an disabled option otherwise it show me the countries. Like in this description https://v2.vuejs.org/v2/guide/conditional.html but unfortunately this is not working on an option HTML element. What i'm missing ?
new Vue({
el: '#app',
data: {
selected: '',
optionAvailable: true,
countries: [
//{ name: 'USA', population: '300M' },
//{ name: 'Canada', population: '100M' },
//{ name: 'Germany', population: '80M' },
]
},
created() {
if(!this.countries.length > 0) {
return this.optionAvailable = false;
}
return true;
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})
html:
<div id="app">
<select #change="onChange($event.target)">
<option v-if="optionAvailable" v-for="(country,index) in countries" :value="country.population">{{ country.name }}</option>
<option v-else disabled>-</option>
</select>
<br>
<span>{{ selected }}</span>
</div>
here jsfiddle:
https://jsfiddle.net/50wL7mdz/434002/
Try this:
template
<div id="app">
<select #change="onChange($event.target)">
<option v-if="countries.length" v-for="(country,index) in countries" :value="country.population">{{ country.name}}</option>
<option v-else>----</option>
</select>
<span>{{ selected }}</span>
</div>
script
new Vue({
el: '#app',
data: {
selected: '',
optionAvailable: true,
countries: [
{ name: 'USA', population: '300M' },
{ name: 'Canada', population: '100M' },
{ name: 'Germany', population: '80M' } ]
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})
You don't need the created hook. You can tell v-if to look at the length of countries directly.
https://jsfiddle.net/z4mu8L9e/8/
try this template
<div id="app">
<select #change="onChange($event.target)" :disabled="!countries.length">
<option v-if="!countries.length" value="">No available countries</option>
<option v-for="(country,index) in countries" :value="country.population">{{ country.name }}</option>
</select>
<br>
<span>{{ selected }}</span>
</div>
Script
new Vue({
el: '#app',
data: {
selected: '',
countries: []
},
methods: {
onChange(event) {
this.selected = event.value;
}
}
})