0

I have form in which there are couple of text fields and an email field. I want to validate all fields for required / mandatory validation. I want to validate email field for email format validation. I want to carry out validation only when I click on two buttons and show the validation messages at top of the page. I know that I can check for email and required validations on field and using ng-show and a flag I can show messages. However I want to check each field's value in a directive and then set the flag to true which will make the message appear.

Here is my HTML. this gets loaded why state provider in main page which also defines following template and a controller for it. so its just a view partial:

          <form name="myForm">
             <div ng-show="validationFailed">
               <!-- here i want to display validation messages using cca.validationMsgs object --> 
            </div>   
             <input type="text" name="test" ng-model="cca.field1" require />
             ....
              <input type="email" mg-model="cca.field2" />
             <input type="button" name="mybutton" /> 
          </form>

Now the controller defined in another JS file:

         'use strict';
         (function(){
                 angular.module('store', []);
                 app.controller("StoreController",function(){
                 var cca = this;
                 cca.validationMsgs = {}; 
                 cca.validationFailed = false; //this flag should decide whether validation messages should be displayed on html page or not.when its true they are shown.
                ...//other mapped fields
            });

And here is unfinished directive which I want to define and write my logic. Logic will be something like this : 1) iterate all elements which have require set on them and check their $validators object / $error.required object is set 2) if yes set validationFailed flag to true,add the validation message to validationMsgs object and break the loop. 3) check if email type field has $error.email object set and if yes similarly set validationFailed flag to true and add corresponding message to the object. Not sure if I really need a directive for this. I would like to apply the directive inside a element.

  app.directive("requireOnSubmit",function(){
         var directiveDefinitionObject = {
              restrict:'E',
               //.... need to fill in 
               //I can use link funcion but not sure how to map
               // validationMsgs and validationFailed objects in here.   
          };
         return directiveDefinitionObject;
  });
5
  • Right now travelling.so can't add code.but I will explain what my idea is. I want iterate all elements in a form and if there is no value in it I want to set a flag. This flag will be true if at least one element does not have value.also I will use this flag in ng-show to display messages.so there are two questions here how to bind the flag in template as well as in a directive ? And this logic should execute when the button is clicked so where to attach the event listeners Commented Jul 5, 2015 at 10:22
  • I added a solution using a factory instead of directive. Take a look at it. Commented Jul 5, 2015 at 10:57
  • @Chrillewoodz I added some code. I tried to explain what I want to do using a directive and the fields in controller I want to map in a directive. I know yours is other way. but not sure which is better. Commented Jul 5, 2015 at 18:03
  • A directive is for DOM manipulation ONLY. It should not contain any logic regarding validation or anything else. This is better off inside a service or factory. My example explain everything very thorough and you should be able to just change certain variables and names to get this working. I've provided a good foundation for you to work from, now it's up to you. Commented Jul 5, 2015 at 18:07
  • @Chrillewoodz Ok let me see if that works thanks. I will accept it if this works Commented Jul 5, 2015 at 18:21

1 Answer 1

1

Without any code or use case to go after I'll just show you a generic way of validating input. I'm going to use a signup functionality as an example.

Create a service/factory which will carry out the validation and return a promise, if the validation fails it will reject the promise. If not, it will resolve it.

Important note: A promise can only be resolved once (to either be fulfilled or rejected), meaning that the first declaration of a resolve or reject will always "win", which means you can't override any resolve or reject. So in this example if a field is empty and a user's email is undefined, the error message will be All fields must be filled in and not Invalid email format.

auth.factory('validation', ['$q', function($q) {
  return {
    validateSignup: function(newUser) {

      var q = $q.defer();

      for (var info in newUser) {
        if (newUser[info] === '') {
          q.reject('All fields must be filled in');
        }
      }

      if (newUser.email === undefined) {
        q.reject('Invalid email format');
      }
      else if (newUser.password.length < 8) {
        q.reject('The password is too short');
      }
      else if (newUser.password != newUser.confirmedPass) {
        q.reject('The passwords do not match');
      }

      q.resolve(true);

      return q.promise;
    }
  }
}]);

And then inject this into your controller

auth.controller('AuthCtrl', ['$scope', '$location', 'validation', function($scope, $location, validation) {

  $scope.status = {
    message: ''
  }

    // Make sure nothing is undefined or validation will throw error
    $scope.newUser = {
      email: '',
      password: '',
      confirmedPass: ''
    }

    $scope.register = function() {

      // Validation message will be set to status.message
      // This will also clear the message for each request
      $scope.status = {
        message: ''
      }

      validation.validateSignup($scope.newUser)
        .catch(function(err) {

          // The validation didn't go through,
          // display the error to the user
          $scope.status.message = err;
        })
        .then(function(status) {

          // If validation goes through
          if (status === true) {

            // Do something
          }
      });
    }

And in the HTML you can have something like this:

<form>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" ng-model="newUser.email">
  </div>
  <div>
    <label for="password">Password:</label>
    <input type="password" id="confirm-pass" ng-model="newUser.password">
  </div>
  <div>
    <label for="confirm-pass">Confirm password:</label>
    <input type="password" id="confirm-pass" ng-model="newUser.confirmedPass">
  </div>
  <div>
    <div>
      <span ng-bind="status.message"></span>
    </div>
  </div>
  <div>
    <button ng-click="register(newUser)">Register</button>
  </div>
</form>

You can use this example and modify it for your use case.

Sign up to request clarification or add additional context in comments.

3 Comments

@Chrillwoodz thanks.will be reaching home in couple of hours will definitely try and will put some code as well so that you get clear picture.thanks though for taking pains to explain without any concrete information from my end
@ShaileshVaishampayan Give it a vote up and accept it as an answer if you find it as an accepted answer to your question.
@Chrillwoodz Can you please have a look at my modified question

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.