【问题标题】:ng-model is not updating when using jquery element.val()使用 jquery element.val() 时,ng-model 未更新
【发布时间】:2014-03-24 14:46:49
【问题描述】:

PLUNKR example here

我正在使用某些版本的 jquery 自动完成作为 angularjs 指令。 当 jquery 使用 element.val() 更新输入值时,角度直到下一个摘要(我想)之后才注意到变化。

我的第一个想法是使用$timeoutng-model 帖子摘要执行操作,但您可以看到它没有帮助。

我的第二种方法是覆盖元素的 val 函数以触发 input 事件,但我没有设法使其工作。

尝试从自动完成列表中选择一个值,您会看到上面的 ng-model 没有更新。

更新

感谢您的回复。我不知道onSelect 选项。

这是根据您的建议编写的代码

// clone user provided options 
scope.options = _.extend({}, scope.AutoCompleteOptions());

// Wrap onSelect - Force update before manipulation on ng-model
var fn = _.has(scope.AutoCompleteOptions(), 'onSelect')  ? scope.AutoCompleteOptions().onSelect : _.noop;
scope.options.onSelect = function () { 
  ngModelCtrl.$setViewValue(element.val()); 
  scope.$apply(fn);
};

scope.autocomplete = $(element).autocomplete(scope.options);

这样我维护指令的接口,同时保证ng-model 是最新的。

谢谢。

【问题讨论】:

    标签: jquery angularjs


    【解决方案1】:

    如您所知,问题在于 Angular 不知道 jquery 插件所做的更新。幸运的是,您可以使用插件的 onSelect 回调来更新 ngModel,如下所示:

    .directive("autoComplete", function() {
        return {
            restrict: "A" , 
            require: 'ngModel', // require ngModel controller
            scope: {
                AutoCompleteOptions : "=autoCompleteOptions", // use '=' instead of '&'
            },
            link: function (scope, element, attrs, ngModelCtrl) {
    
                // prevent html5/browser auto completion
                attrs.$set('autocomplete','off');
    
                // add onSelect callback to update ngModel
                scope.AutoCompleteOptions.onSelect = function() {
                    scope.$apply(function() {
                        ngModelCtrl.$setViewValue(element.val());
                    });
                };
    
                scope.autocomplete = $(element).autocomplete(scope.AutoCompleteOptions);
            }
        }
    });
    

    【讨论】:

      【解决方案2】:

      您使用的插件有一个onSelect 回调,因此您可以简单地修改您的自动完成参数以包含一个更新范围的回调

      {
          lookup      : $scope.current,
          width       : 448,
          delimiter   : /,/,
          tabDisabled : true,
          minChars    : 1,
          onSelect: function(v, data) {
              $scope.selected_tags = v.value;
              $scope.$apply();
      }
      

      编辑

      为了进一步改善这一点,您可以消除在回调中使用模型名称的需要:

      function(v, data) {
          var model = $(this).attr("ng-model");
          $scope[model] = v.value;
          $scope.$apply();
      }
      

      【讨论】:

        【解决方案3】:

        您的 jQuery 插件正在更新输入的视图值,而不是模型。

        您必须修改插件才能访问您的模型或范围,或者您必须绑定一个事件以手动从视图值更新模型。也许是这样的:

        $scope.format_tags = function () { 
        
          $scope.selected_tags = $('#myInput').val();
          $scope.selected_final = _.omit($scope.selected_tags.split(','),_.isEmpty);
        
        };
        

        Here is an updated version of your code using this.

        您可以将事件绑定到实际建议标签元素的点击以获得更好的效果。

        【讨论】:

        • 嘿@Nick,为了使这个指令干燥和独立,我有什么办法可以从auto-complete 指令对element.val() 更改设置ngmodel.$setViewValue(element.val()) 吗?这意味着我将不得不观看 $element.val() 哪个角度目前不允许 - 你知道解决方法吗?
        【解决方案4】:

        我不建议更新插件本身 你可以将你的指令改为这样的东西..

        app.directive("autoComplete", function() { 
            return {
                restrict : "A" , 
                require  : '^ngModel', 
                scope    : 
                {
                    ngModel: '=',
                    AutoCompleteOptions : "&autoCompleteOptions"
                },
                link     : function (scope, element, 
                        // prevent html5/browser auto 
                        attrs.$set('autocomplete','off');
                        var options = scope.
                        options.onSelect = function(elem) {
                             scope.$apply(function() {
                                 scope.ngModel = elem.value;
                             });
                        };
                    scope.autocomplete = $(element).autocomplete(scope.AutoCompleteOptions());
                }
            }
        });
        

        正如您在指令的作用域对象初始化中注意到的那样,我选择了 ngModel 属性作为 AutoComplete Jquery 插件的onSelect 事件使用的东西,我使用scope.$apply() 更新了模型方法。在指令中使用 scope.$apply 以便调用 scope.$digest() 并直接影响模型。

        【讨论】:

          猜你喜欢
          • 2016-10-27
          • 1970-01-01
          • 2014-10-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多