更新ngModel(以及随后的验证)的默认行为是 change ;我想将其更改为 blur 。 docs只能通过以下方式解释如何执行此操作:<ANY ng-model-options="{ updateOn: 'blur' }"></ANY>
。我竟然通过源代码查看,但不知何故找不到 ngModelOptions 和 ng-model-options (尽管文档中都出现了这些内容,源代码)。
答案 0 :(得分:25)
虽然Jon / John编写的ngModel
装饰器提供了一个很好的幕后解决方案,但还必须要注意,声明性地,ngModelOptions
不需要在单个输入字段级别声明,可以在模块级别声明。
<body ng-app = "myApp" ng-model-options="{ updateOn: 'blur' }">
执行上述操作会使myApp
模块中的所有输入字段继承ng-model-options。
如果需要,可以在特定输入字段中覆盖这些字段(例如,搜索过滤器)。
这个plunker演示了:http://plnkr.co/edit/2L1arGgHJwK82xVucJ4p?p=preview
答案 1 :(得分:23)
正如@Angad所提到的,您可以在任何元素上设置ng-model-options,它将应用于其所有后代。但是,问题是,如果你这样设置,无线电和复选框将按预期停止工作:
<body ng-app="myApp" ng-model-options="{ updateOn: 'blur' }">
可以通过向change
添加click
和updateOn
来规避这一点:
<body ng-app="myApp" ng-model-options="{ updateOn: 'change click blur' }">
如果您还想在输入后的某个延迟后更新,可以使用以下内容:
<body ng-app="myApp" ng-model-options="{ updateOn: 'keyup change click blur', debounce: { keyup: 500, click: 0, change: 0, blur: 0 } }">
我在Firefox,Chome,Internet Explorer(10,11)和Safari中测试了这些技术。如果您使用其他事件,请务必通过浏览器对其进行测试,例如在点击后直接在所有浏览器上点击<{1}},然后除了IE。
答案 2 :(得分:12)
这是一个非常好的问题所以我写得更加深入blog article about this。我提出的唯一真正的通用方法是装饰ngModel指令,因为它是真正使用ngModelOptions的指令。
如果查看ngModel指令的角度源,它有一个预链接函数,可以通过使用属性$ options在ngModelController上有效地设置ngModelOptions。注意$ options是在ngModelOptionsDirective中创建的,它实际上是ng-model-options属性的$ eval。
我们需要在ngModel dectorator中执行的操作是在此预绑定函数之后为此$ options属性添加默认值(如果未定义)。我在这里假设,如果开发人员在项目中明确设置了ngModelOptions,他们不希望它神奇地改变!因此,如果$ options属性未定义,我们将只设置默认值。
以下是代码:
(function (angular) {
'use strict';
angular.module('myAppOverridesModule').config(['$provide',
function ($provide) {
$provide.decorator('ngModelDirective', [
'$delegate',
function ($delegate) {
var directive = $delegate[0],
link = directive.link,
shouldSetBlurUpdateEvent = function (nodeName, inputType) {
// The blur event is only really applicable to input controls so
// we want to stick with the default events for selects, checkboxes & radio buttons
return nodeName.toLowerCase() === 'textarea' ||
(nodeName.toLowerCase() === 'input' &&
inputType.toLowerCase() !== 'checkbox' &&
inputType.toLowerCase() !== 'radio');
};
directive.compile = function () {
return function (scope, element, attrs, ctrls) {
var ngModelCtrl = ctrls[0];
link.pre.apply(this, arguments);
// if ngModelOptions is specified leave it unmodified as developer is explicitly setting it.
if (ngModelCtrl.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) {
console.log('set');
ngModelCtrl.$options = {
updateOn: 'blur',
updateOnDefault: false
};
}
link.post.apply(this, arguments);
};
};
return $delegate;
}
]);
}
]);
}(angular));
更新:我已更新代码以忽略选择,复选框和&amp;单选按钮作为模糊事件不是它们的最佳更新事件。
答案 3 :(得分:5)
我修改了Jon Samwell的答案,因为我再也无法让他上班了。
这会覆盖ngModelDirective的编译功能,方法是存储对它的引用,然后返回pre / postLink函数w /对其原始文件的调用以及我们的额外覆盖代码。
享受!
app.config(function($provide) {
$provide.decorator('ngModelDirective', function($delegate) {
var directive = $delegate[0],
link = directive.link,
shouldSetBlurUpdateEvent = function (nodeName, inputType) {
// The blur event is only really applicable to input controls so
// we want to stick with the default events for selects, checkboxes & radio buttons
return nodeName.toLowerCase() === 'textarea' ||
(nodeName.toLowerCase() === 'input' &&
inputType.toLowerCase() !== 'checkbox' &&
inputType.toLowerCase() !== 'radio');
};
// save a reference to the original compile function
var compileFn = directive.compile;
directive.compile = function () {
var link = compileFn.apply(this, arguments);
return {
pre: function ngModelPostLink(scope, element, attr, ctrls) {
if(!ctrls[2]) {
ctrls[2] = {};
}
var ngModelOptions = ctrls[2];
if (ngModelOptions.$options === undefined && shouldSetBlurUpdateEvent(element[0].nodeName, element[0].type)) {
ngModelOptions.$options = {
updateOn: 'blur',
updateOnDefault: false
};
}
link.pre.apply(this, arguments);
},
post: link.post
};
};
return $delegate;
});
});
答案 4 :(得分:2)
而不是使用
ng-model-options="{ updateOn: 'blur' }
你可以使用
ng-model-options="{ debounce : { default : 500 } }"
并将其应用于dom中的父元素,例如容器div。上面的debounce
设置告诉Angular仅在500毫秒无活动后评估验证规则。
使用debounce
这种方法优于使用blur
,因为当应用于整个表单时,模糊会为广播和复选框带来问题。
debounce选项是一个整数值,它会导致模型更新延迟整数毫秒。它降低了$digest
周期发生的频率,这导致js应用程序消耗更少的资源,并允许用户在应用验证规则之前输入时间。
YearOfMoo.com建议像这样使用模糊和去抖动
ng-model-options="{ debounce : { default : 500, blur : 0 } }"
现在,在用户模糊了字段后立即应用模型值和验证。这为blur事件设置了0 ms的等待时间。模糊覆盖默认值。