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.
Related
I have a combobox and want to do something different based on the selected combobox. I use a separate vue.html and TypeScript file.
Here's my code:
<select name="LeaveType" #change="onChange()" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
Here's my TypeScript file:
onChange(value) {
console.log(value);
}
How do I get the selected option value in my TypeScript function?
Use v-model to bind the value of selected option's value. Here is an example.
<select name="LeaveType" #change="onChange($event)" class="form-control" v-model="key">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
<script>
var vm = new Vue({
data: {
key: ""
},
methods: {
onChange(event) {
console.log(event.target.value)
}
}
}
</script>
More reference can been seen from here.
# is a shortcut option for v-on. Use # only when you want to execute some Vue methods. As you are not executing Vue methods, instead you are calling javascript function, you need to use onchange attribute to call javascript function
<select name="LeaveType" onchange="onChange(this.value)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
function onChange(value) {
console.log(value);
}
If you want to call Vue methods, do it like this-
<select name="LeaveType" #change="onChange($event)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
new Vue({
...
...
methods:{
onChange:function(event){
console.log(event.target.value);
}
}
})
You can use v-model data attribute on the select element to bind the value.
<select v-model="selectedValue" name="LeaveType" onchange="onChange(this.value)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
new Vue({
data:{
selectedValue : 1, // First option will be selected by default
},
...
...
methods:{
onChange:function(event){
console.log(this.selectedValue);
}
}
})
Hope this Helps :-)
The changed value will be in event.target.value
const app = new Vue({
el: "#app",
data: function() {
return {
message: "Vue"
}
},
methods: {
onChange(event) {
console.log(event.target.value);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<select name="LeaveType" #change="onChange" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
</div>
You can also use v-model for the rescue
<template>
<select name="LeaveType" v-model="leaveType" #change="onChange()" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
</template>
<script>
export default {
data() {
return {
leaveType: '',
}
},
methods: {
onChange() {
console.log('The new value is: ', this.leaveType)
}
}
}
</script>
onChangeMethod --> method of your choice, it can be anything related to your program.
<template>
<select #change="onChangeMethod($event)">
<option value="test">Test</option>
<option value="test2">Test2</option>
</select>
</template>
<script>
data(){
return{
...
}
},
methods:{
onChangeMethod(event)
{
console.log(event.target.value);
}
},
created(){
...
}
</script>
You can save your #change="onChange()" an use watchers.
Vue computes and watches, it´s designed for that.
In case you only need the value and not other complex Event atributes.
Something like:
...
watch: {
leaveType () {
this.whateverMethod(this.leaveType)
}
},
methods: {
onChange() {
console.log('The new value is: ', this.leaveType)
}
}
I have a combobox and want to do something different based on the selected combobox. I use a separate vue.html and TypeScript file.
Here's my code:
<select name="LeaveType" #change="onChange()" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
Here's my TypeScript file:
onChange(value) {
console.log(value);
}
How do I get the selected option value in my TypeScript function?
Use v-model to bind the value of selected option's value. Here is an example.
<select name="LeaveType" #change="onChange($event)" class="form-control" v-model="key">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
<script>
var vm = new Vue({
data: {
key: ""
},
methods: {
onChange(event) {
console.log(event.target.value)
}
}
}
</script>
More reference can been seen from here.
# is a shortcut option for v-on. Use # only when you want to execute some Vue methods. As you are not executing Vue methods, instead you are calling javascript function, you need to use onchange attribute to call javascript function
<select name="LeaveType" onchange="onChange(this.value)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
function onChange(value) {
console.log(value);
}
If you want to call Vue methods, do it like this-
<select name="LeaveType" #change="onChange($event)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
new Vue({
...
...
methods:{
onChange:function(event){
console.log(event.target.value);
}
}
})
You can use v-model data attribute on the select element to bind the value.
<select v-model="selectedValue" name="LeaveType" onchange="onChange(this.value)" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
new Vue({
data:{
selectedValue : 1, // First option will be selected by default
},
...
...
methods:{
onChange:function(event){
console.log(this.selectedValue);
}
}
})
Hope this Helps :-)
The changed value will be in event.target.value
const app = new Vue({
el: "#app",
data: function() {
return {
message: "Vue"
}
},
methods: {
onChange(event) {
console.log(event.target.value);
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<select name="LeaveType" #change="onChange" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
</div>
You can also use v-model for the rescue
<template>
<select name="LeaveType" v-model="leaveType" #change="onChange()" class="form-control">
<option value="1">Annual Leave/ Off-Day</option>
<option value="2">On Demand Leave</option>
</select>
</template>
<script>
export default {
data() {
return {
leaveType: '',
}
},
methods: {
onChange() {
console.log('The new value is: ', this.leaveType)
}
}
}
</script>
onChangeMethod --> method of your choice, it can be anything related to your program.
<template>
<select #change="onChangeMethod($event)">
<option value="test">Test</option>
<option value="test2">Test2</option>
</select>
</template>
<script>
data(){
return{
...
}
},
methods:{
onChangeMethod(event)
{
console.log(event.target.value);
}
},
created(){
...
}
</script>
You can save your #change="onChange()" an use watchers.
Vue computes and watches, it´s designed for that.
In case you only need the value and not other complex Event atributes.
Something like:
...
watch: {
leaveType () {
this.whateverMethod(this.leaveType)
}
},
methods: {
onChange() {
console.log('The new value is: ', this.leaveType)
}
}
I am new to vue.js. I'm stuck trying to dynamically set the options of one select based on the selected value in another.
For example, I have two dropdowns named division and district.
var A = [{1: 'a'},{2:'b'}];
If value of A is 1, then the district select should load the related codes. I can do it with jQuery but not with Vue.
Here is my template.
<div class="form-group" :class="class_obj">
<select name="div_code" v-model="div_code" class="form-control" required>
<option value="">Choose One</option>
<option v-for="option in div_list" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
</div>
<div class="form-group" :class="class_label">
<label for="">District</label>
</div>
<div class="form-group" :class="class_obj">
<select name="dist_code" v-model="dist_code" class="form-control" required>
<option value="">Choose One</option>
</select>
</div>
Here is my javascript.
export default {
data():{
div_list: [
{'1': "ABC"} , {'2': "DEF"}
];
}
}
How can I load the dist_code select with related data from ajax when div_code value is 1?
Handle a change event on the div_code change
<select name="div_code"
v-model="div_code"
#change="onDivCodeChange"
class="form-control"
required>
<option value="">Choose One</option>
<option v-for="option in div_list" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
And add the onDivCodeChange method to your Vue.
methods:{
onCodeChange(){
// make an ajax call and set the options for your
// dist_code here. For example:
$.ajax({
url: "...",
data: {div_code: this.div_code},
success: codes => this.code_list = codes
error: err => console.log(err)
})
}
}
And of course add code_list as a property of your data and update your template.
<select name="dist_code" v-model="dist_code" class="form-control" required>
<option value="">Choose One</option>
<option v-for="code in code_list" :value="code.value">{{code.text}}</option>
</select>
Create computed property. Basically, when data property changes(should be used in computed property) the computed property will update itself.
As in below example, when message property changes the reverseMessage will update itself.
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
1- In your example, bind your first dropdown value to a data property.
2 -Create a computed property for the second dropdown and use the data
property in it.
3 -Write the template of it.
Done.
When the first dropdown changes the second dropdown will update itself.
Note: Vue documentation advise to use Watcher for Ajax requests instead of computed properties. Both are very similar.
https://v2.vuejs.org/v2/guide/computed.html#Watchers
My component vue is like this :
<template>
<select class="form-control" v-model="selected" :required #change="changeLocation">
<option :selected>Choose Province</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
I use this : <option :selected>Choose Province</option> to selected
But whene executed, on the gulp watch exist error
The error like this :
ERROR in
./~/vue-loader/lib/template-compiler.js?id=data-v-53777228!./~/vue-load
er/lib/selector.js?type=template&index=0!./resources/assets/js/components/bootst
rap/LocationBsSelect.vue Module build failed: SyntaxError: Unexpected
token (28:4)
Seems my step is wrong
How can I solve it?
Handling the errors
You are binding properties to nothing. :required in
<select class="form-control" v-model="selected" :required #change="changeLocation">
and :selected in
<option :selected>Choose Province</option>
If you set the code like so, your errors should be gone:
<template>
<select class="form-control" v-model="selected" :required #change="changeLocation">
<option>Choose Province</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
Getting the select tags to have a default value
you would now need to have a data property called selected so that v-model works. So,
{
data () {
return {
selected: "Choose Province"
}
}
}
If that seems like too much work, you can also do it like:
<template>
<select class="form-control" :required="true" #change="changeLocation">
<option :selected="true">Choose Province</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
When to use which method?
You can use the v-model approach if your default value depends on some data property.
You can go for the second method if your default selected value happens to be the first option.
You can also handle it programmatically by doing so:
<select class="form-control" :required="true">
<option
v-for="option in options"
v-bind:value="option.id"
:selected="option == '<the default value you want>'"
>{{ option }}</option>
</select>
The simplest answer is to set the selected option to true or false.
<option :selected="selectedDay === 1" value="1">1</option>
Where the data object is:
data() {
return {
selectedDay: '1',
// [1, 2, 3, ..., 31]
days: Array.from({ length: 31 }, (v, i) => i).slice(1)
}
}
This is an example to set the selected month day:
<select v-model="selectedDay" style="width:10%;">
<option v-for="day in days" :selected="selectedDay === day">{{ day }}</option>
</select>
On your data set:
{
data() {
selectedDay: 1,
// [1, 2, 3, ..., 31]
days: Array.from({ length: 31 }, (v, i) => i).slice(1)
},
mounted () {
let selectedDay = new Date();
this.selectedDay = selectedDay.getDate(); // Sets selectedDay to the today's number of the month
}
}
<select v-model="challan.warehouse_id">
<option value="">Select Warehouse</option>
<option v-for="warehouse in warehouses" v-bind:value="warehouse.id" >
{{ warehouse.name }}
</option>
Here "challan.warehouse_id" come from "challan" object you get from:
editChallan: function() {
let that = this;
axios.post('/api/challan_list/get_challan_data', {
challan_id: that.challan_id
})
.then(function (response) {
that.challan = response.data;
})
.catch(function (error) {
that.errors = error;
});
}
You simply need to remove v-bind (:) from selected and required attributes.
Like this :-
<template>
<select class="form-control" v-model="selected" required #change="changeLocation">
<option selected>Choose Province</option>
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
You are not binding anything to the vue instance through these attributes thats why it is giving error.
My code for reactive multiselect
data() {
return {
article: {title: 'aaaaa', 'categoriesIds': [1,3], ...},
selectCategories: {1: 'xxx', 2: 'www', 3: 'yyy', 4: 'zzz'},
}
},
template
<div class="form-group">
<label for="content">Categories</label>
<select name="categories"
v-model="article.categoriesIds"
id="categories"
multiple
class="form-control col-md-5"
size="6">
<option v-for="(category, key) in selectCategories"
:key="key"
v-bind:value="key">{{category}}</option>
</select>
</div>
Selected items are binded to the article.categoriesIds array.
Another way, which I often find more reliable, is you could add a directive to your app.js or wherever you are initiating your VueJS, eg:
Vue.directive('attr', (el, binding) => {
if (binding.value === true) binding.value = ''
if (binding.value === '' || binding.value) {
el.setAttribute(binding.arg, binding.value)
}
})
You can then utilise v-attr to set an attribute, eg:
<option value="Western Australia" v-attr:selected="form.state == 'Western Australia'">Western Australia</option>
So as I understand the main goal is to set "Choose Province" as the default. I tried other options but the simple one worked for me the best:
<template>
<select class="form-control" v-model="selected" :required #change="changeLocation">
<option>Choose Province</option> # just an option with no selected or assigned v-model
<option v-for="option in options" v-bind:value="option.id" >{{ option.name }}</option>
</select>
</template>
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;
}