Hi I'm using this modified wrapper to handle a multiple select for vue.js. I'm trying to change value of this inside vue component. Here is my code.
<select2-multiple :options="car_options" v-model="input.classification">
<option disabled value="0">Select one</option>
</select2-multiple>
And this is my script,
Vue.component('select2Multiple', {
props: ['options', 'value'],
template: '#select2-template',
mounted: function () {
var vm = this
$(this.$el)
// init select2
.select2({ data: this.options })
.val(this.value)
.trigger('change')
// emit event on change.
.on('change', function () {
vm.$emit('input', $(this).val())
})
},
watch: {
value: function (value) {
alert(value);
if ([...value].sort().join(",") !== [...$(this.$el).val()].sort().join(","))
$(this.$el).val(value).trigger('change');
},
options: function (options) {
// update options
$(this.$el).select2({ data: options })
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
});
var vm = new Vue({
el: '#el',
delimiters: ["[[", "]]"],
data: {
input: {
classification: []
},
},
created: function () {
var vm = this;
axios.get('http://jsonplaceholder.typicode.com/todos')
.then(function (response) {
$.each(response.data, function (i, item) {
response.data[i].id = String(response.data[i].id);
response.data[i].text = String(response.data[i].title);
vm.car_options.push(response.data[i]);
});
vm.input.classification = ["2"];
})
.catch(function (error) {
console.log(error);
});
}
});
I need to get vm.input.classification = ["2"] selected by default. And it's not working and no error message displays. I'm no expert in vue components but I feel like issue relies on vue component.
Here is a js fiddle for my example,
Finally I found the answer. We need to swapp the positions of options and value of component watch.
watch: {
options: function (options) {
// update options
$(this.$el).select2({ data: options })
},
value: function (value) {
if ([...value].sort().join(",") !== [...$(this.$el).val()].sort().join(","))
$(this.$el).val(value).trigger('change');
}
},
Related
I am trying to build a menu between categories. If a category has a sub-category it returns a value that says has_subCategory as boolean 0/1.
<template>
<select><slot></slot></select>
</template>
<script>
export default {
props: ['value',
'hasSubCat'],
watch: {
value: function(value, hasSubCat) {
this.relaod(value);
this.fetchSubCategories(value, hasSubCat);
}
},
methods: {
relaod: function(value) {
var select = $(this.$el);
select.val(value || this.value);
select.material_select('destroy');
select.material_select();
},
fetchSubCategories: function(value, hasSubCat) {
var mdl = this;
var catID = value || this.value;
var has_subCat = hasSubCat || this.hasSubCat;
console.log("has_subCat:" + has_subCat);
mdl.$emit("reset-subcats");
if (catID) {
if (has_subCat == 0) {
if ($('.subdropdown').is(":visible") == true) {
$('.subdropdown').fadeOut();
}
} else {
axios.get(URL.API + '/subcategories/' + catID)
.then(function(response) {
response = response.data.subcatData;
response.unshift({
subcat_id: '0',
subcategory_name: 'All Subcategories'
});
mdl.$emit("update-subcats", response);
$('.subdropdown').fadeIn();
})
.catch(function(error) {
if (error.response.data) {
swal({
title: "Something went wrong",
text: "Please try again",
type: "error",
html: false
});
}
});
}
} else {
if ($('.subdropdown').is(":visible") == true) {
$('.subdropdown').fadeOut();
}
}
}
},
mounted: function() {
var vm = this;
var select = $(this.$el);
select
.val(this.value)
.on('change', function() {
vm.$emit('input', this.value);
});
select.material_select();
},
updated: function() {
this.relaod();
},
destroyed: function() {
$(this.$el).material_select('destroy');
}
}
</script>
<material-selectcat v-model="catId" name="category" #reset-subcats="resetSubCats" #update-subcats="updateSubCats" id="selcat">
<option v-for="cat in cats" :value="cat.cat_id" :hasSubCat="cat.has_subCat" v-text="cat.category_name"></option>
</material-selectcat>
The data looks like this:
cat_id:"0"
category_name:"All Subcategories"
has_subCat:0
What I dont understand is that console.log("has_subCat:" + hasSubCat); prints out different values each time I change the select. It should only display 0 or 1
Watcher in vue.js is supposed to be used in order to watch one value, but you can fulfill your requirement with help of computed.
export default {
props: ['value',
'hasSubCat'],
watch: {
/* without this, watcher won't be evaluated */
watcher: function() {}
},
computed: {
watcher: function() {
this.reload(this.value);
this.fetchSubCategories(this.value, this.hasSubCat);
}
},
...
}
I also made a simplified working fiddle, you can have a look.
You are assuming that the second parameter of your watch function is hasSubCat which is not the case. While the first parameter of the value watch function represents the new value of the property, the second parameter is actually the old value of the watched property. Try this out to understand more.
watch: {
value: function(value, oldValue) {
console.log('new value:', value)
console.log('old value:', oldValue)
}
}
So to watch both of value and hasSubCat, you can do something like this:
watch: {
value: function(newValue) {
this.reload(newValue)
this.fetchSubCategories(newValue, this.hasSubCat)
},
hasSubCat: function(newHasSubCat) {
this.reload(this.value)
this.fetchSubCategories(this.value, newHasSubCat)
}
}
I have an app that holds the student list data. The component is supposed to take in that list and render a select dropdown (with select2).
In the fiddles console, it's displaying jQuery is not defined. I thought all fiddles now included jQuery?
I'm really not sure why this is breaking the all together. Is there something wrong with my directive? I know with Vue 2.0 they removed params, but this should suffice. Any eyes on my code would be greatly appreciated.
// Define component
var studentsComponent = Vue.extend({
props: ['students'],
data(): {
return {}
},
methods:{},
directives: {
select: {
bind: function () {
var self = this;
var select = $('#select-student');
select.select2();
select.on('change', function () {
console.log('hey on select works!');
});
},
update: function (oldVal, newVal) {
var select = $('#select-student');
select.val(newVal).trigger('change');
}
},
},
template: `
<div>
<select
ref=""
id="select-student"
v-select>
<option value="0">Select Student</option>
<option
v-for="(student, index) in students"
:value="student.id">
{{ student.name }}
</option>
</select>
</div>
`,
});
// Register component
Vue.component('students-component', studentsComponent);
// App
new Vue({
el: '#app',
data: {
students: [
{ name: 'Jack', id: 0 },
{ name: 'Kate', id: 1 },
{ name: 'Sawyer', id: 2 },
{ name: 'John', id: 3 },
{ name: 'Desmond', id: 4 },
]
},
});
I made a fiddle https://jsfiddle.net/hts8nrjd/4/ for reference. Thank you for helping a noob out!
First, as I mentioned in comments, I would suggest you do this with a component. If you had to stick with a directive, however, you can't initialize select2 in the bind hook. You've defined your options in the DOM, so you need to wait until the component is inserted to initialize it.
directives: {
select: {
inserted: function (el, binding, vnode) {
var select = $(el);
select.select2();
select.on('change', function () {
console.log('hey on select works!');
});
},
},
},
Here is an update of your fiddle.
Trying to use this component.
<select2 v-model="value" :options="options" #change="onChange()"></select2>
The #change callback is not getting called. I know that I can use watch: { value: function () { ... } but, is there a way to capture underlying tag events?
In the current version, select2 component does not handle on-change function. For this, you have to modify the select2 component, you have to add one more prop: onChange and inside component execute the function passed in this prop, changes will be something like following:
Vue.component('select2', {
props: ['options', 'value', 'onChange'], //Added one more prop
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)
//New addition to handle onChange function
if (this.onChange !== undefined) {
this.onChange(this.value)
}
})
},
watch: {
value: function (value) {
// update value
$(this.$el).select2('val', value)
},
options: function (options) {
// update options
$(this.$el).select2({ data: options })
}
},
destroyed: function () {
$(this.$el).off().select2('destroy')
}
})
Now, you can pass a function which will be executed onChange like following:
<select2 v-model="value" :options="options" :on-change="onChange()"></select2>
As title says, I registered Select2 directive for VueJS 1.0.15 using example from their page.
I want to catch #change event but it doesn't work.
HTML:
<select v-select="item.service" :selected="item.service" #change="serviceChange(item)">
<option value="1">test 1</option>
<option value="2">test 2</option>
</select>
JS:
Vue.directive('select', {
twoWay: true,
params: ['selected'],
bind: function () {
var self = this
$(this.el)
.select2({
minimumResultsForSearch: Infinity
})
.val(this.params.selected)
.on('change', function () {
console.log('changed');
self.set(this.value);
})
},
update: function (value) {
$(this.el).val(value).trigger('change')
},
unbind: function () {
$(this.el).off().select2('destroy')
}
});
var Checkout = new Vue({
el: '.Checkout',
methods: {
serviceChange: function (item) {
console.log(item);
},
}
});
Expanded on Alberto Garcia answer.
var selectDropDown = $(".select-drop-down").select2();
selectDropDown.on('select2:select', function (e) {
var event = new Event('change');
e.target.dispatchEvent(event);
});
Yeah, I encountered this problem. Haven't figured out the solution yet, but this is my current work-a-round using watch:
In your VueJS:
watch: {
/**
* Watch changes on the select2 input
*
* #param integer personId
*/
'person': function (personId) {
var personName = $("#person").select2('data')[0].text
this.doSomethingWithPerson(personId, personName)
}
},
Then in your HTML:
<select
id="person"
v-select2="person"
class="form-control"
data-options="{{ $peopleJSON }}"
data-placeholder="Choose a person"
>
</select>
Note: In the above HTML, {{ $peopleJSON }} is just how I insert my server-side JSON using Blade template engine. Not really pertinent to the question.
I recently had a problem trying to bind a select2 result to a vuejs data model object, and I came with a workaround, it might help you:
https://jsfiddle.net/alberto1el/7rpko644/
var search = $(".search").select2({
ajax: {
url: "/echo/json",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term
};
},
processResults: function (data, params) {
var mockResults = [{id: 1,text: "Option 1"}, {id: 2,text: "Option 2"}, {id: 3,text: "Option 3"}];
return {results: mockResults};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1
});
search.on("select2:select", function (e){
$('.result_search').val( $(this).val() ).trigger( 'change' );
});
var vm = new Vue({
el: "#app",
data: {
busqueda_result : ''
}
});
I know you are using a directive but maybe it helps you
shouldn't you use $emit?
update: function (value) {
$(this.el).val(value);
this.$emit('change');
}
I'm having trouble with a Backbone.js tutorial from Treehouse. Here's my code:
var NotesApp = (function () {
var App = {
stores: {}
}
App.stores.notes = new Store('notes');
// Note Model
var Note = Backbone.Model.extend({
//Local Storage
localStorage: App.stores.notes,
initialize: function () {
if (!this.get('title')) {
this.set({
title: "Note at " + Date()
})
};
if (!this.get('body')) {
this.set({
body: "No Body"
})
};
}
})
//Views
var NewFormView = Backbone.View.extend({
events: {
"submit form": "createNote"
},
createNote: function (e) {
var attrs = this.getAttributes(),
note = new Note();
note.set(attrs);
note.save();
},
getAttributes: function () {
return {
title: this.$('form [name=title]').val(),
body: this.$('form [name=body]').val()
}
}
});
window.Note = Note;
$(document).ready(function () {
App.views.new_form = new NewFormView({
el: $('#new')
});
})
return App
})();
And I get the error: Cannot set property 'new_form' of undefined
I've tried to go back and copy the code as close as possible, but I still couldn't get it to work. Any suggestions?
After stores: {} add ,
views: {}.
You need an object to attach your view to - JavaScript has no vivification