Angular指令不会在ngModel中触发更改事件

时间:2013-12-18 08:11:17

标签: javascript angularjs angularjs-directive angularjs-select2

我为输入元素创建了一个指令,用于创建自定义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/

2 个答案:

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

这是jsFiddle demo

希望这有用。

答案 1 :(得分:0)

由于element不是scope尝试的一部分而使用function代替它,所以<{1}}

scope.$watch(function () {
  return element;
}, function () {
  console.log('x');
});