使用 jquery-chosen 插件更新 vuejs 模型值
Update vuejs model value using jquery-chosen plugin
尝试在 vue 中使用 jquery-chosen,问题是这个插件隐藏了我应用 v-model
的实际 select,所以当我 select 一个值 vue未将其识别为 select 更改事件并且模型值未更新。
select 的值实际上在我 select 时发生了变化,我用 console.log 检查了它以查看 selected 值。
http://jsfiddle.net/qfy6s9Lj/3/
我可以 vm.$data.city = $('.cs-select').val()
,that 似乎可行,
但是还有另一种选择吗?如果更改了 select 的值,为什么 vue 看不到这个?
我对其他建议持开放态度,但暂时我是这样做的:
html
<div id='search-results'>
{{city}}
<select class="cs-select" v-model='city'>
<option value="Toronto">Toronto</option>
<option value="Orleans">Orleans</option>
</select>
</div>
js
window.vm = new Vue({
el: '#search-results',
data: {
city: 'Toronto',
}
})
$('.cs-select').chosen({
inherit_select_classes: true,
width: '30%'
}).change( function() {
vm.$data.city = $('.cs-select').val()
})
回答:
http://jsfiddle.net/qfy6s9Lj/5/
<div id='search-results'>
Vue model value <br>
{{city}}
<hr>
Select value:
<select class="cs-select" v-chosen>
<option value="Toronto">Toronto</option>
<option value="Orleans">Orleans</option>
</select>
</div>
Vue.directive('chosen', {
bind: function () {
var vm = this.vm;
this.el.options = vm.cities;
this.el.value = vm.city;
$(this.el).chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999})
.change( function() {
vm.city = this.el.value;
}.bind(this)
);
}
});
var vm = new Vue({
data: {
city: 'Toronto',
cities: ['Toronto', 'Orleans']
}
}).$mount("#search-results");
更新:更好的解决方案(感谢 simplesmiler):
http://jsfiddle.net/simplesmiler/qfy6s9Lj/8/
@swift 的答案非常接近,但正如@bertrand 指出的那样,它不适用于多选。我已经制定了适用于这两种情况的方法:http://jsfiddle.net/seanwash/sz8s99xx/
我本来想发表评论,但我没有足够的代表来发表评论。
Vue.directive('chosen', {
twoWay: true, // note the two-way binding
bind: function () {
$(this.el)
.chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999
})
.change(function(ev) {
// two-way set
// Construct array of selected options
var i, len, option, ref;
var values = [];
ref = this.el.selectedOptions;
for (i = 0, len = ref.length; i < len; i++) {
option = ref[i];
values.push(option.value)
}
this.set(values);
}.bind(this));
},
update: function(nv, ov) {
// note that we have to notify chosen about update
$(this.el).trigger("chosen:updated");
}
});
var vm = new Vue({
data: {
city: 'Toronto',
cities: [{text: 'Toronto', value: 'Toronto'},
{text: 'Orleans', value: 'Orleans'}]
}
}).$mount("#search-results");
我更新了 vue2。
Vue.directive('chosen', {
selected: null,
inserted: function (el, binding) {
selected = binding.value;
$(el).chosen().change(function(event, change) {
if(change.hasOwnProperty('selected')) {
selected.push(change.selected);
} else {
selected.splice(selected.indexOf(change.deselected), 1);
}
});
},
componentUpdated: function(el, binding) {
selected = binding.value;
$(el).trigger("chosen:updated");
}
});
var vm = new Vue({
el: '#app',
data: {
selected: [],
cities: [{id: 1, value: "Toronto"}, {id: 2, value: "Orleans"}, {id: 3, value: "Bern"}]
}
});
更新: 请注意,这在 v-for
循环中不起作用。 here.
提供了一个相关的问题来解决这个问题
离开@kaktuspalme 的解决方案,在我朋友 Joe Fleming 的帮助下,我想出了一个适用于 Vue 2 并允许单选和多选的解决方案:
Vue.directive('chosen', {
inserted: function(el, binding, vnode) {
jQuery(el).chosen().change(function(event, change) {
if (Array.isArray(binding.value)) {
var selected = binding.value;
if (change.hasOwnProperty('selected')) {
selected.push(change.selected);
} else {
selected.splice(selected.indexOf(change.deselected), 1);
}
} else {
var keys = binding.expression.split('.');
var pointer = vnode.context;
while (keys.length > 1)
pointer = pointer[keys.shift()];
pointer[keys[0]] = change.selected;
}
});
},
componentUpdated: function(el, binding) {
jQuery(el).trigger("chosen:updated");
}
});
这样使用:
<select v-model="mymodel" v-chosen="mymodel">...</select>
它适用于 multiple="multiple"
甚至嵌套状态,例如:
<select v-model="nested.mymodel" v-chosen="nested.mymodel">...</select>
在此处查看 fiddle:https://jsfiddle.net/tylercollier/bvvvgyp0/5/
代码取自@kaktuspalme 回答。它现在适用于非多重元素,并且仅适用于非多重元素。
Vue.directive('chosensingle', {
inserted: function (el, binding) {
var selected = binding.value;
$(el).chosen().change(function(event, change) {
if(change.hasOwnProperty('selected')) {
selected.value = change.selected;
} else {
selected.value ='';
}
});
},
componentUpdated: function(el, binding) {
$(el).trigger("chosen:updated");
}
});
考虑了@Tyler Collier 的评论
但要小心,属性 你在 v-model 中使用的应该定义为 array ,例如applicantId: [] 否则不行
尝试在 vue 中使用 jquery-chosen,问题是这个插件隐藏了我应用 v-model
的实际 select,所以当我 select 一个值 vue未将其识别为 select 更改事件并且模型值未更新。
select 的值实际上在我 select 时发生了变化,我用 console.log 检查了它以查看 selected 值。
http://jsfiddle.net/qfy6s9Lj/3/
我可以 vm.$data.city = $('.cs-select').val()
,that 似乎可行,
但是还有另一种选择吗?如果更改了 select 的值,为什么 vue 看不到这个?
我对其他建议持开放态度,但暂时我是这样做的:
html
<div id='search-results'>
{{city}}
<select class="cs-select" v-model='city'>
<option value="Toronto">Toronto</option>
<option value="Orleans">Orleans</option>
</select>
</div>
js
window.vm = new Vue({
el: '#search-results',
data: {
city: 'Toronto',
}
})
$('.cs-select').chosen({
inherit_select_classes: true,
width: '30%'
}).change( function() {
vm.$data.city = $('.cs-select').val()
})
回答: http://jsfiddle.net/qfy6s9Lj/5/
<div id='search-results'>
Vue model value <br>
{{city}}
<hr>
Select value:
<select class="cs-select" v-chosen>
<option value="Toronto">Toronto</option>
<option value="Orleans">Orleans</option>
</select>
</div>
Vue.directive('chosen', {
bind: function () {
var vm = this.vm;
this.el.options = vm.cities;
this.el.value = vm.city;
$(this.el).chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999})
.change( function() {
vm.city = this.el.value;
}.bind(this)
);
}
});
var vm = new Vue({
data: {
city: 'Toronto',
cities: ['Toronto', 'Orleans']
}
}).$mount("#search-results");
更新:更好的解决方案(感谢 simplesmiler): http://jsfiddle.net/simplesmiler/qfy6s9Lj/8/
@swift 的答案非常接近,但正如@bertrand 指出的那样,它不适用于多选。我已经制定了适用于这两种情况的方法:http://jsfiddle.net/seanwash/sz8s99xx/
我本来想发表评论,但我没有足够的代表来发表评论。
Vue.directive('chosen', {
twoWay: true, // note the two-way binding
bind: function () {
$(this.el)
.chosen({
inherit_select_classes: true,
width: '30%',
disable_search_threshold: 999
})
.change(function(ev) {
// two-way set
// Construct array of selected options
var i, len, option, ref;
var values = [];
ref = this.el.selectedOptions;
for (i = 0, len = ref.length; i < len; i++) {
option = ref[i];
values.push(option.value)
}
this.set(values);
}.bind(this));
},
update: function(nv, ov) {
// note that we have to notify chosen about update
$(this.el).trigger("chosen:updated");
}
});
var vm = new Vue({
data: {
city: 'Toronto',
cities: [{text: 'Toronto', value: 'Toronto'},
{text: 'Orleans', value: 'Orleans'}]
}
}).$mount("#search-results");
我更新了 vue2。
Vue.directive('chosen', {
selected: null,
inserted: function (el, binding) {
selected = binding.value;
$(el).chosen().change(function(event, change) {
if(change.hasOwnProperty('selected')) {
selected.push(change.selected);
} else {
selected.splice(selected.indexOf(change.deselected), 1);
}
});
},
componentUpdated: function(el, binding) {
selected = binding.value;
$(el).trigger("chosen:updated");
}
});
var vm = new Vue({
el: '#app',
data: {
selected: [],
cities: [{id: 1, value: "Toronto"}, {id: 2, value: "Orleans"}, {id: 3, value: "Bern"}]
}
});
更新: 请注意,这在 v-for
循环中不起作用。 here.
离开@kaktuspalme 的解决方案,在我朋友 Joe Fleming 的帮助下,我想出了一个适用于 Vue 2 并允许单选和多选的解决方案:
Vue.directive('chosen', {
inserted: function(el, binding, vnode) {
jQuery(el).chosen().change(function(event, change) {
if (Array.isArray(binding.value)) {
var selected = binding.value;
if (change.hasOwnProperty('selected')) {
selected.push(change.selected);
} else {
selected.splice(selected.indexOf(change.deselected), 1);
}
} else {
var keys = binding.expression.split('.');
var pointer = vnode.context;
while (keys.length > 1)
pointer = pointer[keys.shift()];
pointer[keys[0]] = change.selected;
}
});
},
componentUpdated: function(el, binding) {
jQuery(el).trigger("chosen:updated");
}
});
这样使用:
<select v-model="mymodel" v-chosen="mymodel">...</select>
它适用于 multiple="multiple"
甚至嵌套状态,例如:
<select v-model="nested.mymodel" v-chosen="nested.mymodel">...</select>
在此处查看 fiddle:https://jsfiddle.net/tylercollier/bvvvgyp0/5/
代码取自@kaktuspalme 回答。它现在适用于非多重元素,并且仅适用于非多重元素。
Vue.directive('chosensingle', {
inserted: function (el, binding) {
var selected = binding.value;
$(el).chosen().change(function(event, change) {
if(change.hasOwnProperty('selected')) {
selected.value = change.selected;
} else {
selected.value ='';
}
});
},
componentUpdated: function(el, binding) {
$(el).trigger("chosen:updated");
}
});
考虑了@Tyler Collier 的评论
但要小心,属性 你在 v-model 中使用的应该定义为 array ,例如applicantId: [] 否则不行