Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add error into form validation error list in angular?

I'm using ng-messages to validate my registration form fields, but I have a problem, I can't check if username is taken, until I send registration request to server. Currently I have this type of code:

UserPool.signUp(vm.form.username, vm.form.password, attributes)
    .then(function (result) {
        $state.go('app.pages_auth_confirm', {
            user: result.user
        });
    })
    .catch(function () {
        $scope.registerForm.username.$invalid = true;
        $scope.registerForm.username.$error.usernameAlreadyExists = true;
    });

and HTML:

<input name="username" ng-model="vm.form.username" placeholder="Name" required>
<div ng-messages="registerForm.username.$error" role="alert">
    <div ng-message="required">
        <span>Username field is required</span>
    </div>
    <div ng-message="usernameAlreadyExists">
        <span>User with this username already exists</span>
    </div>
</div>

and this works, but I want to know proper way of implementing that functionality. Registration form has many other fields also and changing some of them manually, for showing error, doesn't seems to be a good idea. I also did some research about validations and messages in angular and found out about custom validation and $asyncValidators but I can't use that functionality neither because as I understood I'll be needing some kind of API for getting information about used usernames only, but I don't have that kind of possibility, as I already said, I can't check if username is taken, until I send registration request. So can anybody tell me what should I do? What is the proper way for working with this kind of validation?

like image 755
GROX13 Avatar asked Oct 03 '16 11:10

GROX13


People also ask

How do you show error message in form?

In order to display error messages on forms, you need to consider the following four basic rules: The error message needs to be short and meaningful. The placement of the message needs to be associated with the field. The message style needs to be separated from the style of the field labels and instructions.

How do you show error in reactive form?

When multiple validations are involved in a single formControl, we need to put multiple *ngIf in the HTML and bind the respective validator's error messages which makes the code clumsy.

How do I add a validation message in reactive form?

html file, add the ngIf directive to show the message when the form is submitted and the required validator is true. Save the changes and run the app. Click on the sign-in button without entering the first name and you will be able to see the required validation message.


2 Answers

In order to achieve this in an angular way, create a Directive in the user-name input to check for the unique validation, and a factory to make an api call to get the username validation checked.

<input name="username" ng-model="vm.form.username" placeholder="Name" required name="username" unique> 

<div ng-messages="registerForm.username.$error" role="alert">
    <div ng-message="required">
        <span>Username field is required</span>
    </div>
    <div ng-message="unique">
        <span>User with this username already exists</span>
    </div>
</div>

the directive can be something like this,

In this directive we injected a factory called usernameservice, which returns the promise true or false.

myApp.directive('unique', function(usernameservice) {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, element, attrs, ngModel) {
      ngModel.$asyncValidators.unique = usernameservice;
    }
  };
});

Here is the factory, where your api call goes.

myApp.factory('usernameservice', function($q, $http) {
  return function(username) {
    var deferred = $q.defer();

    // your api vall goes her
    $http.get('/api/users/' + username).then(function() { // 
      // Found the user, therefore not unique.
      deferred.reject();
    }, function() {
      // User not found, therefore unique!
      deferred.resolve();
    });

    return deferred.promise;
  }
});

Now the message will be displayed every time the value is changed, let us delay the check so that, if user enter more letters, it gets called, let us use the ng-model-option debounce for it.

<input name="username" ng-model="vm.form.username" placeholder="Name" required name="username" unique ng-model-options="{ debounce: 100 }">  
like image 137
Sravan Avatar answered Oct 16 '22 15:10

Sravan


This kind of code works for just adding validation error into the array:

$scope.registerForm.username.$setValidity("usernameAlreadyExists", false);

this should be called in catch block like this:

...
.catch(function () {
    $scope.registerForm.username.$setValidity("usernameAlreadyExists", false);
});

This code doesn't flags any of the form variables manually instead it uses interface method $setValidity which sets every necessary variable as needed.

like image 32
GROX13 Avatar answered Oct 16 '22 16:10

GROX13