【问题标题】:Angularjs: input[text] ngChange fires while the value is changingAngularjs:输入[文本] ngChange 在值更改时触发
【发布时间】:2012-08-05 19:00:12
【问题描述】:

ngChange 在值更改时触发(ngChange 与经典的 onChange 事件不同)。如何将经典的 onChange 事件与 angularjs 绑定,只有在提交内容时才会触发?

当前绑定:

<input type="text" ng-model="name" ng-change="update()" />

【问题讨论】:

  • 只是在寻找类似的东西,我突然想到您可能还想考虑仅在该字段有效时进行更新。这样,用户可以努力将输入转换为有效格式(或者您可以通过提示和过滤器帮助他们),然后您可以在他们正确时奖励他们更新!
  • 一个更灵活的解决方案,允许指定要使用的事件(不仅仅是模糊)和其他属性应该很快内置到角度:github.com/angular/angular.js/pull/2129

标签: angularjs


【解决方案1】:

This post 显示了一个指令示例,该指令延迟模型对输入的更改,直到blur 事件触发。

Here 是一个小提琴,它显示了 ng-change 与新的 ng-model-on-blur 指令一起使用。请注意,这是对 original fiddle 的轻微调整。

如果您将指令添加到您的代码中,您会将绑定更改为:

<input type="text" ng-model="name" ng-model-onblur ng-change="update()" />

指令如下:

// override the default input to update on blur
angular.module('app', []).directive('ngModelOnblur', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        priority: 1, // needed for angular 1.2.x
        link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });         
            });
        }
    };
});

注意:正如@wjin 在下面的 cmets 中提到的,Angular 1.3(目前处于测试阶段)通过 ngModelOptions 直接支持此功能。请参阅the docs 了解更多信息。

【讨论】:

  • 警告,elm.unbind('input') 在 Internet Explorer 8 中引发“TypeError”,因此根本不会执行其他 unbind 语句。我通过将 elm.unbind('input') 移动到单独的行并用 try/catch 块包围它来解决它。
  • Angular 1.2 有一个ng-blur 指令:docs.angularjs.org/api/ng.directive:ngBlur
  • 我使这段代码工作,但我必须设置指令的优先级(即优先级:100)。我正在使用 Angular 1.2.10。我的猜测是 ngModelOnblur 指令在 ngModel 指令之前运行,所以还没有什么可以解除绑定的。此外,此页面看起来将来可能会有内置解决方案:github.com/angular/angular.js/pull/1783
  • 注意至少在 Angular 1.3 中,默认实现通过 ng-model-options="{ updateOn: 'default blur' }" 支持此功能,请参阅 documentation
  • @RobJuurlink(或任何其他在尝试绑定或取消绑定到“输入”时遇到 IE8“TypeError”的人) - 查看 Angular 的源代码,您会看到他们使用 $sniffer 来确定如果浏览器支持“输入”,如果不支持,则返回到“keydown”。如果您将上述指令更新为仅在 $sniffer.hasEvent('input') 返回 true 时解除绑定“输入” - 那么您可以避免该错误并仍然在 IE8 中工作
【解决方案2】:

如果其他人在寻找额外的“输入”按键支持,这里是 Gloppy 提供的 fiddle 的更新

按键绑定代码:

elm.bind("keydown keypress", function(event) {
    if (event.which === 13) {
        scope.$apply(function() {
            ngModelCtrl.$setViewValue(elm.val());
        });
    }
});

【讨论】:

    【解决方案3】:

    对于任何在 IE8 上苦苦挣扎的人(它不喜欢 unbind('input'),我找到了解决方法。

    将 $sniffer 注入你的指令并使用:

    if($sniffer.hasEvent('input')){
        elm.unbind('input');
    }
    

    如果你这样做,IE8 会平静下来 :)

    【讨论】:

    • 或者只使用 try/catch
    【解决方案4】:

    覆盖默认输入 onChange 行为(仅调用函数 当控制损失焦点和价值发生变化时)

    注意:ngChange 与它触发的经典 onChange 事件不同 值更改时的事件 该指令存储值 获得焦点时的元素
    在模糊它检查是否 新值已更改,如果更改,则触发事件

    @param {String} - "onChange" 时要调用的函数名 应该被解雇

    @example

    angular.module('app', []).directive('myOnChange', function () { 
        return {
            restrict: 'A',
            require: 'ngModel',
            scope: {
                myOnChange: '='
            },
            link: function (scope, elm, attr) {
                if (attr.type === 'radio' || attr.type === 'checkbox') {
                    return;
                }
                // store value when get focus
                elm.bind('focus', function () {
                    scope.value = elm.val();
    
                });
    
                // execute the event when loose focus and value was change
                elm.bind('blur', function () {
                    var currentValue = elm.val();
                    if (scope.value !== currentValue) {
                        if (scope.myOnChange) {
                            scope.myOnChange();
                        }
                    }
                });
            }
        };
    });
    

    【讨论】:

      【解决方案5】:

      使用$scope.$watch不是更好地反映作用域变量的变化吗?

      【讨论】:

      【解决方案6】:

      这是关于 AngularJS 的最新添加,作为未来的答案(也适用于 another question)。

      Angular 较新的版本(现在在 1.3 beta 中),AngularJS 原生支持这个选项,使用 ngModelOptions,比如

      ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"
      

      NgModelOptions docs

      例子:

      <input type="text" name="username"
             ng-model="user.name"
             ng-model-options="{updateOn: 'default blur', debounce: {default: 500, blur: 0} }" />
      

      【讨论】:

      • 它在 1.3 beta 5 中无法正常工作,但在当前主版本 2602 中已修复
      • 这就是为什么它仍处于测试阶段,无法在“现实世界”应用程序中使用,例如我现在正在构建的应用程序。
      • 这是一个 ng-model-options 类似 Angular 1.2.x 的模块 github.com/fergaldoyle/modelOptions
      【解决方案7】:

      据我所知,我们应该在 select 选项中使用 ng-change,在文本框的情况下我们应该使用 ng-blur。

      【讨论】:

      • 这是现在的正确答案,当时问这个问题时显然不存在。
      • 非常感谢...这应该是答案
      【解决方案8】:

      我遇到了完全相同的问题,这对我有用。添加ng-model-updateng-keyup,一切顺利!这是docs

       <input type="text" name="userName"
               ng-model="user.name"
               ng-change="update()"
               ng-model-options="{ updateOn: 'blur' }"
               ng-keyup="cancel($event)" />
      

      【讨论】:

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