我为输入元素创建了一个指令,用于创建自定义select2下拉列表
选择元素后,原始输入字段(用于通过ngModel过滤数据)将填充下拉列表中的选定数据,但不会触发输入的更改事件。
如果我手动更改输入值,则过滤器正在工作。
这是我的指令的代码。
.directive('ajaxSelect2', ['$timeout', function($timeout) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
switch(element.prop("tagName")) {
case 'INPUT':
$timeout(function() {
element.select2({
[ ... ] //the select2 part
});
});
break;
}
/* update the input value */
element.bind("change", function(e) {
scope.$apply(function() {
scope[attrs.ngModel] = e.val;
});
});
scope.$watch(element, function () {
console.log('x'); //not called
});
}
}
}])
我认为element.bind("change")
中的scope.apply()
会触发视图更新,但它不起作用。
有没有人知道如何告诉ngModel它有新数据?
编辑:我发现,问题是ngModel。因为我必须过滤多个值,所以我的模型是filter.foobar
。这不起作用。如果我将模型更改为foobar
,它将起作用。我创造了一个小提琴来说明:http://jsfiddle.net/StinsonMaster/6t3Nt/3/
答案 0 :(得分:1)
我已经实现了自定义select2下拉指令。并将change事件处理程序注册到指向链接的元素。当我从下拉列表中选择一个项目时,将触发input元素的change事件。 一切都按预期工作。你可以尝试我的实现:
指令
.directive('ajaxSelect2',['$timeout', function($timeout){
return {
restrict: 'A',
link: function(scope, element, attrs){
element.select2({
width: '200px',
createSearchChoice:function(term, data) { if ($(data).filter(function() { return this.text.localeCompare(term)===0; }).length===0) {return {id:term, text:term};} },
multiple: true,
data: [{id: 0, text: 'story'},{id: 1, text: 'bug'},{id: "ccc", text: 'task'}]
});
element.bind("change",function(e){
scope.$apply(function(){
scope[attrs.ngModel] = e.val.toString();
});
});
}
};
}]);
HTML
<body ng-app="selectApp">
<div ng-controller="selectCtrl">
<span>Selcted value: {{input}}</span>
<div>
<input id="test2" ng-model="input" ajax-select2/>
</div>
</div>
</body>
以下是JSBin DEMO
[编辑]有关财产访问问题
自定义select2元素的ng模型是“filter.foo”。您希望通过select2下拉过滤器通知角度世界ng-model的值已更新。但你不能像这样访问二级属性:
scope[attrs.ngModel] = e.val; // equal to scope['filter.foo'] which is the first level property 'filter.foo'
您应该以这种方式访问该属性:
var props = attrs.ngModel.split(".");
if(props.length>1){
scope[props[0]][props[1]] = e.val; //[] equals to dot '.'
}else{
scope[attrs.ngModel] = e.val;
}
希望这有用。
答案 1 :(得分:0)
由于element
不是scope
尝试的一部分而使用function代替它,所以<{1}}
scope.$watch(function () {
return element;
}, function () {
console.log('x');
});