使用 jquery element.val() 时,ng-model 未更新
我正在使用某些版本的 jquery 自动完成功能作为 angularjs 指令.当 jquery 使用 element.val()
更新输入值时,angular 直到下一个摘要(我想)之后才会注意到变化.
I'm using some version of jquery autocomplete as an angularjs direcitve.
When the jquery updates the input's value using element.val()
angular does no notice the change until after the next digest ( i suppose ).
我的第一个想法是使用 $timeout
对 ng-model
帖子摘要执行操作,但如您所见,它没有帮助.
My first thought was to perform the action on the ng-model
post digest using $timeout
but as you can see it didn't help.
我的第二种方法是覆盖元素的 val
函数以触发 input
事件,但我还没有设法让它工作.
My second approach was to override the element's val
function to trigger an input
event but I haven`t managed to make it work.
尝试从自动完成列表中选择一个值,您会看到上面的 ng-model 没有更新.
Try to select a value from the autocomplete list and you'll see that the ng-model above is not updating.
更新
感谢您的回复.我不知道 onSelect
选项.
Thanks for the response. I didn't know about the onSelect
option.
这是根据您的建议编写的代码
This is the code based on your recommendations
// 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
将是最新的.
This way i maintain the interface of the directive while guarantying that ng-model
will be up to date.
谢谢.
正如您已经知道的,问题是 angular 不知道 jquery 插件所做的更新.幸运的是,您可以使用插件的 onSelect
回调来更新 ngModel,如下所示:
As you already knew, the problem is angular doesn't aware of the update made by jquery plugin. Luckily, you can use the plugin's onSelect
callback to update ngModel, like this:
.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);
}
}
});