2

我为输入元素创建了一个指令,该指令创建了一个自定义的 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")inscope.apply()会触发视图更新,但它不起作用。有人知道如何告诉 ngModel 它有新数据吗?

编辑:我想通了,问题是 ngModel。因为我必须过滤几个值,所以我的模型是filter.foobar. 这是行不通的。如果我将模型更改为foobar,它将起作用。我创建了一个小提琴来说明:http: //jsfiddle.net/StinsonMaster/6t3Nt/3/

4

2 回答 2

1

我已经实现了一个自定义的 select2 下拉指令。并将更改事件处理程序注册到指令链接到的元素。当我从下拉列表中选择一个项目时,将触发输入元素的更改事件。一切都按预期工作。你可以试试我的实现:

指示

.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 演示

[编辑] 对于属性访问问题

自定义 select2 元素的 ng-model 是“filter.foo”。您想通知角度世界 ng-model 的值已由 select2 下拉过滤器更新。但是您不能像这样访问二级属性:

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;
}

这是一个jsFiddle 演示

希望这会有所帮助。

于 2013-12-19T08:21:05.390 回答
0

因为element不是scope尝试使用返回它的函数的一部分:

scope.$watch(function () {
  return element;
}, function () {
  console.log('x');
});
于 2013-12-18T09:48:09.457 回答