Vue.js <select> v-model not binding within component - javascript

I am trying Vue.js, everything looks great other than working with select inputs within components.
I created a basic fiddle setup to illustrate the problem :
https://jsfiddle.net/8f24xLdq/
<div class="panel-body" id="vue">
<example></example>
</div>
<script type="text/x-template" id="t">
<div>
<select v-bind="selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<script>
Vue.component('example', {
template: "#t",
data: function() {
return {
selected: 'A',
options: [{
text: 'One',
value: 'A'
}, {
text: 'Two',
value: 'B'
}, {
text: 'Three',
value: 'C'
}]
}
}
});
new Vue({
el: "#vue"
});
</script>

Use v-model instead of v-bind in <select >
<select v-model="selected">

<div class="col-md-6">
<select v-model="selectedto">
<option v-for="option in estados" v-bind:value="option.id" :key="option.id" v-html="option.label">
</option>
</select>
<span v-html="selectedto"></span>
</div>
mounted: function () {
console.log('created', this);
var vm = this;
vm.$root.selectedto = 1;
}

Related

How do I render options and optgroups conditionally with v-for?

I have a data structured like this
const options = [
{
group: 'Fruits', options: [
{ label: 'Apple', value: 'f-1' },
{ label: 'Banana', value: 'f-2' },
{ label: 'Orange', value: 'f-3' },
],
},
{ label: 'Chocolate', value: 'm-1' },
{ label: 'Cake', value: 'm-2' },
{
group: 'Vegetables', options: [
{ label: 'Cabbage', value: 'v-1' },
{ label: 'Tomato', value: 'v-2' },
],
},
{ label: 'Puddin', value: 'm-3' },
]
I would like to render it into a select component like this:
<select>
<optgroup label="Fruits">
<option value="f-1">Apple</option>
<option value="f-2">Banana</option>
<option value="f-3">Orange</option>
</optgroup>
<option value="m-1">Chocolate</option>
<option value="m-2">Cake</option>
<optgroup label="Vegetables">
<option value="v-1">Cabbage</option>
<option value="v-2">Tomato</option>
</optgroup>
<option value="m-3">Pudding</option>
</select>
I tried something like this but it gave me an error:
<select>
<optgroup v-for="group in options" v-if="group.group" :label="group.group" :key="group.group">
<option v-for="option in group" :key="option.value" :value="option.value">{{ option.label }}</option>
</optgroup>
<option v-for="option in options" v-if="!option.group" :key="option.value" :value="option.value">{{ option.label }}</option>
</select>
The 'options' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'
Any ideas on how should I render it correctly? I'm kinda struggling with this for a while, thanks in advance!
This is where the non-rendering <template> tag comes in handy
const options = [{"group":"Fruits","options":[{"label":"Apple","value":"f-1"},{"label":"Banana","value":"f-2"},{"label":"Orange","value":"f-3"}]},{"label":"Chocolate","value":"m-1"},{"label":"Cake","value":"m-2"},{"group":"Vegetables","options":[{"label":"Cabbage","value":"v-1"},{"label":"Tomato","value":"v-2"}]},{"label":"Puddin","value":"m-3"}]
new Vue({
el: "#app",
data: () => ({ options, selected: null })
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
<select v-model="selected">
<template v-for="option in options">
<!-- if the `group` property is truthy -->
<optgroup v-if="option.group" :label="option.group" :key="option.group">
<option v-for="opt in option.options" :value="opt" :key="opt.value">
{{ opt.label }}
</option>
</optgroup>
<!-- otherwise -->
<option v-else :value="option" :key="option.value">
{{ option.label }}
</option>
</template>
</select>
<pre>selected = {{ selected }}</pre>
</div>
Note that you cannot put key attributes on <template> so those should go where appropriate on the elements within.
In the example above, I've also bound the entire option object instead of just the value but you can choose the best value to bind for your usage.

Using Value of Option in select in Vue

In the following:
<select id="test">
<option value="1">Test One</option>
<option value="2">Test Two</option>
</select>
I want is, When i select the option, The value of selected option should appear in input box. Like when i click Test One, the input box should say 1 as selected
Is it possible to do this in Vue?
You have to used v-model to get the selected item from <select>
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
</select>
<span>Selected: {{ selected }}</span>
In Javascript
new Vue({
el: '...',
data: {
selected: ''
}
})
I hope you got what you want!
You can accomplish this by using the #change event handler
<select #change="handleChange">
<option
v-for="item in options"
:value="item.value"
v-text="item.letter"
/>
</select>
new Vue({
el: "#app",
data: {
selected: undefined,
options: [
{ letter: 'A', value: '1' },
{ letter: 'B', value: '2' },
]
},
methods: {
handleChange({ target: { value } }) {
this.selected = value
}
},
})
Check out this fiddle

Vue.js dont re-render after select element change

using Vue.js.
I have two object arrays, category and categoryPar, category contains name and parent's name, categoryPar contains just name. I want to display only categories that belongs to selected parent. Trying to do it like this:
<select v-model="editing.categoryPar"">
<option v-for="cat in categoryPar" v-bind:value="cat.name">{{ cat.description }}</option>
</select>
<select v-model="editing.category">
<option v-for="cat in category" v-if="editing.categoryPar == cat.par_name" v-bind:value="cat.name">{{ cat.description }}</option>
</select>
Condition is fulfilled but not re-rendered. When I use in console vue.$forceUpdate(); then it works, till I change parent select.
Thank you for help.
You need to create a variable of your selected model first.
Currently you are giving your v-model an object, which is why it is not working
new Vue({
el: '#app',
data () {
return {
selectedCategory: '',
category: [{name: 'A', parent: 'Alpha'}, {name: 'B', parent: 'Bravo'}, {name: 'C', parent: 'Charlie'}],
categoryPar: [{name: 'A'}, {name: 'B'}, {name: 'C'}],
}
},
})
<script src="https://unpkg.com/vue#2.5.9/dist/vue.js"></script>
<div id="app">
<pre>Selected Cat: {{selectedCategory}}</pre>
<select name="" id="" v-model='selectedCategory'>
<option :value="cat.name" v-for="cat in category"> {{ cat.name }}</option>
</select>
<select name="" id="">
<option value="" v-for="cat in categoryPar" v-if="cat.name === selectedCategory"> {{ cat.name }}</option>
</select>
</div>

How do i bind select box with input in vuejs?

I try to bind select box with input so I have a select box with pre defined options and when selected that option will be in the input and when the user types text in the input a dynamic new select option should be made if it is not in the pre defined list else it should match on one of the items.
<div class="col-md-2 text-center">
<select class="form-control" v-model="selected">
<option v-for="item in inventory" :value="item" :key="item.id">
#{{ item.name }}
</option>
</select>
<p>
#{{ selected.id}}
</p>
</div>
<input v-model="inputBind" placeholder="," type="text" class="form-control">
and
new Vue({
el:'#app',
data:{
inputBind:'',
inventory: [
{name: 'MacBook Air', id: 1},
{name: 'MacBook Pro', id: 2},
{name: 'Lenovo W530', id: 3},
{name: 'Acer Aspire One', id: 4}
],
selected: 2
},
created: function() {
this.selected = this.inventory.find(i => i.id === this.selected);
},
Use the the same data attr for the input, check js fiddle that way data is shared by both the inputs. Its is the easiest way. Note that for the select box to select the correct option now you must enter the matching value. Don't know what the reason is you need it this way but its not that user friendly.
Js
new Vue({
el: '#app',
data: {
selected: 'item1',
input: '',
items: {
1: {id: 1, val: 'item1'},
2: {id: 2, val: 'item2'},
3: {id: 3, val: 'item3'},
}
}
});
Html
<div id="app">
<select class="form-control" v-model="selected">
<option v-for="item in items" :value="item.val" :key="item.id">
{{ item.val }}
</option>
</select>
<p>
{{ selected }}
</p>
<input v-model="selected" placeholder="," type="text" />
</div>
You can bind to change and which is fired after the model value has been updated like so:
<select class="form-control" v-model="selected" #change="doSomethingWithChangedValue">
<option v-for="item in inventory" :value="item" :key="item.id">
#{{ item.name }}
</option>
</select>

Select2 with Vue Js as directive

I have been following the vue js wrapper component example. I am trying to change how this works to allow me to add a v-select2 directive to a regular select box rather than have to create templates and components for each one.
I have a JS Bin here which shows using the component.
The component html is as follows (with the options being set in the JS).
<div id="app"></div>
<script type="text/x-template" id="demo-template">
<div>
<p>Selected: {{ selected }}</p>
<select2 :options="options" v-model="selected">
<option disabled value="0">Select one</option>
</select2>
<p>Selected: {{ selected2 }}</p>
<select2 :options="options" v-model="selected2">
<option disabled value="0">Select one</option>
</select2>
<p>Selected: {{ selected3 }}</p>
<select2 :options="options" v-model="selected3">
<option disabled value="0">Select one</option>
</select2>
</div>
</script>
<script type="text/x-template" id="select2-template">
<select>
<slot></slot>
</select>
</script>
With the JS as follows:
Vue.component('select2', {
props: ['options', 'value'],
template: '#select2-template',
mounted: function () {
var vm = this
$(this.$el)
.val(this.value)
// init select2
.select2({ data: this.options })
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
})
},
watch: {
value: function (value) {
// update value
$(this.$el).val(value)
},
options: function (options) {
// update options
$(this.$el).select2({ data: options })
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
})
var vm = new Vue({
el: '#app',
template: '#demo-template',
data: {
selected: 0,
selected2: 0,
selected3: 0,
options: [
{ id: 1, text: 'Hello' },
{ id: 2, text: 'World' }
]
}
})
What I want is something like the following
<div id="app">
<p>Selected: {{ selected }}</p>
<select name="selected1" id="selected1" class="select2" v-selectize v-model="selected">
... options here ...
</select>
<p>Selected: {{ selected2 }}</p>
<select name="selected2" id="selected2" class="select2" v-selectize v-model="selected2">
... options here ...
</select>
<p>Selected: {{ selected3 }}</p>
<select name="selected3" id="selected3" class="select2" v-selectize v-model="selected3">
... options here ...
</select>
</div>
You can use your component in pretty much the way you want to use your directive:
<select2 name="selected1" id="selected1" v-model="selected">
<option disabled value="0">Select one</option>
<option value="1">Hello</option>
<option value="2">World</option>
</select2>
The name and id attributes get transferred to the underlying select element.
There is no (good) way to do this with a directive, which is an intentional design decision in Vue 2. There is no communication channel between a directive and the Vue as there is between a component and its parent component. A directive is not a sub-Vue, as a component is, it is a way of dealing with a small piece of the DOM in isolation.
I do not think there would be any particular advantage to writing this with a directive rather than a component.

Categories