用户离开字段后验证字段

mcr*_*n18 91 forms angularjs

使用AngularJS,我可以使用ng-pristineng-dirty检测用户是否已进入该字段.但是,我想在用户离开字段区域后才进行客户端验证.这是因为当用户输入电子邮件或电话等字段时,他们将始终收到错误,直到他们完成输入完整的电子邮件,这不是最佳的用户体验.


更新:

Angular现在附带自定义模糊事件:https: //docs.angularjs.org/api/ng/directive/ngBlur

use*_*145 92

从版本1.3.0开始,这可以很容易地完成$touched,这在用户离开现场后就是如此.

<p ng-show="form.field.$touched && form.field.$invalid">Error</p>
Run Code Online (Sandbox Code Playgroud)

https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

  • 但是,这里的一个重大缺陷是,如果你回到现场,你将无法获得相同的验证经验.你回到了第一个方位,它在每次按键时都会验证,因为它已经设置为触摸.我很惊讶这有很多赞成票. (5认同)
  • @dudewad这是正确的,但我认为这是明智的行为 - 如果你回到无效字段,错误消息应该持续到值有效,直到你键入第一个字母. (3认同)

poc*_*sar 75

角1.3现在已经NG-模型选项,您可以将选项设置为{ 'updateOn': 'blur'}例如,你甚至可以去抖,当使用或者是打字速度太快,或者你想节省一些昂贵的DOM操作(如型号写入到多个DOM位置,你不希望每个键都发生$ digest循环)

https://docs.angularjs.org/guide/forms#custom-triggershttps://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates

默认情况下,对内容的任何更改都将触发模型更新和表单验证.您可以使用ngModelOptions指令覆盖此行为,以仅绑定到指定的事件列表.即,模型选项="{updateOn:'blur'}"仅在控件失去焦点后才会更新和验证.您可以使用空格分隔列表设置多个事件.即模型选项="{updateOn:'mousedown blur'}"

去抖动

您可以使用带有ngModelOptions指令的去抖键来延迟模型更新/验证.此延迟也适用于解析器,验证器和模型标志,如$ dirty或$ pristine.

即,在触发模型更新和表单验证之前,自上次内容更改后,等模型选项="{debounce:500}"将等待半秒钟.

  • 在大多数情况下,这并不能解决问题,因为您可能仍希望在用户离开字段之前收到`ng-change`事件.例如,在我的情况下,只要输入字段有效,我就会从我的API请求新数据,但我不想在它无效时立即显示错误消息 - 我只想在它出现时执行此操作无效且发生模糊事件. (2认同)

lam*_*tor 32

我通过扩展@jlmcdonald的建议来解决这个问题.我创建了一个自动应用于所有input和select元素的指令:

var blurFocusDirective = function () {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, elm, attr, ctrl) {
            if (!ctrl) {
                return;
            }

            elm.on('focus', function () {
                elm.addClass('has-focus');

                scope.$apply(function () {
                    ctrl.hasFocus = true;
                });
            });

            elm.on('blur', function () {
                elm.removeClass('has-focus');
                elm.addClass('has-visited');

                scope.$apply(function () {
                    ctrl.hasFocus = false;
                    ctrl.hasVisited = true;
                });
            });

            elm.closest('form').on('submit', function () {
                elm.addClass('has-visited');

                scope.$apply(function () {
                    ctrl.hasFocus = false;
                    ctrl.hasVisited = true;
                });
            });

        }
    };
};

app.directive('input', blurFocusDirective);
app.directive('select', blurFocusDirective);
Run Code Online (Sandbox Code Playgroud)

当用户关注/访问元素时,这将为各种元素添加has-focushas-visited类.然后,您可以将这些类添加到CSS规则中以显示验证错误:

input.has-visited.ng-invalid:not(.has-focus) {
    background-color: #ffeeee;   
}
Run Code Online (Sandbox Code Playgroud)

这很有效,因为元素仍会获得$ invalid属性等,但CSS可用于为用户提供更好的体验.

  • 说实话,你不应该偏离设置输入字段状态的角度方式,比如`formName.inputName.$ dirty`.我建议编辑这个指令来写一个类似于`formName.inputName.$ focused`的布尔值,而不是使用模糊名称和布尔值进行验证. (5认同)
  • 为什么需要'?ngModel'而不仅仅是'ngModel'?我明白要求ngModel在那里,但为什么问号呢? (2认同)
  • 谢谢你的想法.应该指出它需要jQuery(我认为 - 在jql中看不到.closest()). (2认同)

nic*_*las 16

我设法用一个非常简单的CSS来做到这一点.这确实要求错误消息是它们所涉及的输入的兄弟,并且它们具有一类error.

:focus ~ .error {
    display:none;
}
Run Code Online (Sandbox Code Playgroud)

满足这两个要求之后,这将隐藏与聚焦输入字段相关的任何错误消息,我认为angularjs应该做的事情.似乎是疏忽.

  • 这种方法的缺点是当有人纠正错误时,错误不再可见,这是不理想的.理想的是,错误直到模糊才会显示,但在纠正之前不会消失. (5认同)
  • 啊.这是一个聪明的方法.我更喜欢写这个javascript来做这件事. (2认同)

Arg*_*g0n 5

这似乎在较新版本的 angular 中作为标准实现。

NG-不变NG-触摸之前分别被设置并且用户之后已聚焦的验证元件上。

CSS

input.ng-touched.ng-invalid {
   border-color: red;
}
Run Code Online (Sandbox Code Playgroud)