Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Toggle $setValidity after model change

I'm creating a signup form in Angular with three inputs: email, password and passwordConfirm. My controller looks like this:

app.controller('SignupController', function ($scope, User) {
    $scope.user = {};

    $scope.signup = function() {
        User.save($scope.user, function(success) {
            // TODO
        }, function(error) {
            if (error.status === 422) {
                error.data.errors.forEach(function(item) {
                    $scope.signupForm[item.field].$setValidity(item.error, false);
                });
            }
        });
    };
});

What this is doing is sending a request to my API when the user submits the form to register themselves. If a 422 response comes back (which means validation errors), I loop through them and set the corresponding inputs to invalid based on what the API returned.

Let's take the example of an email address already being registered. I show the validation error in my view like this:

<small class="error" ng-show="signupForm.email.$error.exists">Email address taken, please use another</small>

This all works perfectly, but my user is now stuck because when they try to change the email address to another one, the validity of the email field isn't changed to allow them to resubmit the form (I disable the submit button based on form validity).

Basically, I need the validation property (in this case exists) to be reset to true after the user changes the input model. What's the best way for me to do that?

Edit: A small brainwave hit me after posting, I added this to my controller:

$scope.$watch('user.email', function() {
    // Reset exists validation property back to true
    $scope.signupForm.email.$setValidity('exists', true);
});

which seems to work. When the user changes the model value after the input was set to invalid, this sets it back to valid. But this doesn't strike me as the best way to do this. Anyone know better?

like image 276
John Dorean Avatar asked Nov 10 '22 16:11

John Dorean


1 Answers

I have also struggled with this issue. After reading your post I came up with a possible solution - create a directive that is watching the model for changes and reset the validity state on change (basically what you suggested but put in a generic directive)

angular.module('app').directive('resetValidityOnChange', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, iElem, iAttrs, ngModelCtrl) {
            ngModelCtrl.$viewChangeListeners.push(function () {
                ngModelCtrl.$setValidity(iAttrs['resetValidityOnChange'], true);
            });
        }
    }
}

You will have to add this directive to the input's you would like to reset, for instance:

<input type="text" ng-model="vm.email" reset-validity-on-change="exists" />
like image 152
Ivan Avatar answered Nov 14 '22 22:11

Ivan