lambinator
lambinator

Reputation: 11009

Controlling when validation happens in angular

Is it possible to control when angular's form validations run? Specifically, I want to show fields as invalid only when

  1. A field as received and lost focus (blur)
  2. The user tries to submit

and I want to hide it while the field has focus.

The default behavior of Angular of showing validation errors on forms when it first loads seems like a bad user experience to me. I've been able to get this partially working on blur for the require attribute using using the pattern from here, but I really don't want to have to re-implement all the validations.

Is it possible to control this timing globally?

Upvotes: 1

Views: 1007

Answers (1)

lambinator
lambinator

Reputation: 11009

I ended up solving this by using a custom directive that adds focus/blur properties and classes to each of the form's controls:

app.directive('input', 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;
                });
            });

        }
    };
});

With this in place, you can control the error highlighting on input fields through some plain ol css:

input.has-visited.ng-invalid:not(.has-focus) {
    background-color: #ffeeee;   
}

And check for form.<element>.hasVisited when showing the validation error messages.

Hope this helps someone else. :)

Upvotes: 3

Related Questions