使用jquery element.val()时ng-model没有更新

时间:2014-03-24 14:46:50

标签: jquery angularjs

PLUNKR example here

我使用某种版本的jquery autocomplete作为angularjs direcitve。 当jquery使用element.val() angular更新输入的值时,直到下一个摘要(我猜)之后才会注意到更改。

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

我的第二种方法是覆盖元素的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将是最新的。

感谢。

4 个答案:

答案 0 :(得分:5)

正如您已经知道的那样,问题是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);
        }
    }
});

答案 1 :(得分:1)

您使用的插件有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();
}

答案 2 :(得分:0)

您的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.

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

答案 3 :(得分:0)

我不建议您更新插件本身 你可以改变你的指令而不是像这样......

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()方法。使用范围。$ apply在一个指令中,以便调用范围。$ digest()并直接影响模型。