0

I am using the Angular 1.5.2, building the validations on the top of the ng-messages. Basically, that is supposed to be like this, and certainly that works.

<form name="myform" class="form-horizontal">
    <h1>{{myform.name.$error}}!</h1>
    <input type="text" class="form-control" name="name" ng-model="name" required maxlength="3">
      <div ng-messages="myform.name.$error" role="alert">
        <div ng-message="maxlength">max length</div>
        <div ng-message="required">required</div>
      </div>
    </input>
  </form>

However, I am thinking about a way to inject the validation rules and validation message dynamically, the idea is that I will create a directive (named "validate"), the directive is supposed to be add necessary attributes like "required", "maxlength", .... and also append ng-messages as well, like this

<form name="myform" class="form-horizontal">
    <h1>{{myform.name.$error}}!</h1>
    <input type="text" class="form-control" name="name" ng-model="name" validate />
  </form>

app.directive('validate', ['$compile', function ($compile) {
return {
    restrict: 'A',
    replace: false,
    compile: function(element, attrs) {
        element.removeAttr("ng-required");
        element.attr("ng-required", "true");

        element.removeAttr("maxlength");
        element.attr("maxlength", "3");

        var validationMessages = angular.element('<div ng-messages="myform.name.$error" role="alert"><div ng-message="maxlength">max length</div><div ng-message="required">required</div></div>');
        element.append(validationMessages)
    }
};}]);

My directive doesn't work, I see attributes are already added, ng-messages is also appended, but the validation is not working, something I am doing wrong?

my plunker: https://plnkr.co/edit/GAd9UdcHxCDyV6dH1Q7e

khoailang
  • 725
  • 1
  • 15
  • 32

3 Answers3

0

https://plnkr.co/edit/wBPp6TamWtC6tDxwyDyz?p=preview

HTMl

 <form name="signupForm" ng-submit="vm.submit()" class="p-t-30">

                <div class="col-md-12 form-group fg-float p-0 m-t-5">
                    <div class="fg-line">
                        <input type="email" name="signupEmail" ng-model="vm.reqObj.user.personalEmailId" class="form-control" required="">
                    </div>
                    <label class="fg-label f-white">Email</label>
                    <div ng-show="signupForm.$submitted || signupForm.signupEmail.$touched" class="red">
                        <small ng-show="signupForm.signupEmail.$error.required" class="f-input-error f-700">Enter email</small> 
                        <small ng-show="signupForm.signupEmail.$error.email" class="f-input-error f-700">Enter valid email</small>
                    </div>
                </div>



                 <div class="clearfix"></div>
                <div class="col-md-12 form-group fg-float p-0 m-t-5">
                    <div class="fg-line">
                        <input type="password" name="password" class="form-control" ng-model="vm.reqObj.user.password" required="" />
                    </div>
                    <label class="fg-label f-white">Password</label>
                    <div ng-show="signupForm.$submitted || signupForm.password.$touched" class="red">
                        <small ng-show="signupForm.password.$error.required" class="f-input-error f-700">Enter password</small>
                    </div>
                </div>
                <div class="col-md-12 form-group fg-float p-0 m-t-5">
                    <div class="fg-line">
                        <input type="password" name="confirmPassword" class="form-control" ng-model="vm.reqObj.user.password1" required="" compare-to="vm.reqObj.user.password" />
                    </div>
                    <label class="fg-label f-white">Confirm Password</label>
                    <div ng-show="signupForm.$submitted || signupForm.confirmPassword.$touched" class="red">
                        <small ng-show="signupForm.confirmPassword.$error.required" class="f-input-error f-700">Enter confirm password</small> 
                        <small ng-show="signupForm.confirmPassword.$error.compareTo" class="f-input-error f-700">Password does not match</small>
                    </div>
                </div>
                <div class="text-left">
                    <span class="f-white f-300">By continuing, I agree to the 
                        <a class="f-white f-700">Seller Agreement</a> and <a class="f-white f-700">Privacy Policy</a>
                    </span>
                </div>
               <div class="text-center">
                     <button type="submit" class="btn login-btn" value="log in" ng-disabled="!signupForm.$valid"><span data-ng-if="vm.BtnTxt=='Signing up...'"><i class="glyphicon glyphicon-refresh spinning white f-s-16 l-h-0"></i>&nbsp;</span>colick</button>
                </div>
            </form>

and Directive

app.directive('compareTo', function(){
           return {
             require: "ngModel",
             scope: {
               otherModelValue: "=compareTo"
             },
             link: function(scope, element, attributes, ngModel) {

               ngModel.$validators.compareTo = function(modelValue) {
                 return modelValue == scope.otherModelValue;


               };

               scope.$watch("otherModelValue", function() {
                 ngModel.$validate();
               });
             }
           };
   });
Gayathri Mohan
  • 2,924
  • 4
  • 19
  • 25
  • thank you for the idea, but it doesn't look like what I need – khoailang Jun 08 '16 at 13:10
  • this is your question how to inject validation attributes dynamically inside angular directive according to the question which u ask the above plunker satisified, how come you can say doesn't look like what i need – Gayathri Mohan Jun 09 '16 at 01:13
  • 1. sorry if the title doesn't summarize the whole question posted 2. as you see in my plunker https://plnkr.co/edit/GAd9UdcHxCDyV6dH1Q7e, the validation attributes are not in the static html template, they are injected runtime inside the directive, I am using ng-messages, it is working if all of them are in the html upfront, but in my example, the validation doesn't work when injected runtime, I am not sure if that is a right approach or something I missed. thank you. – khoailang Jun 09 '16 at 03:30
  • do you think I need to post another question, to get it more clear? – khoailang Jun 09 '16 at 03:31
0

Hi please check the updated answer which the exact result

script.js

 var myapp = angular.module("myapp", ['ngMessages']);

myapp.controller("mycontroller", ['$scope', function($scope){

}]);

myapp.directive('validate', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        require: "ngModel",
         scope: {
               otherModelValue: "= maxLength"
             },
        replace: false,
          link: function(scope, element, attributes, ngModel) {

               ngModel.$validators.maxLength = function(modelValue) {
                 if(modelValue.length > scope.otherModelValue)
                 {
                    console.log(modelValue.length == scope.otherModelValue)
                  return modelValue.length == scope.otherModelValue;
                 }



               };

               scope.$watch("otherModelValue", function() {
                 ngModel.$validate();
               });
             }

    };
}]);

and HTMl

<!DOCTYPE html>
<html>

<head>
  <script src="https://code.angularjs.org/1.5.2/angular.js"></script>
  <script src="https://code.angularjs.org/1.5.2/angular-messages.js"></script>
  <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>

</head>

<body>
  <document ng-app="myapp">
    <div ng-controller="mycontroller">
      <form name="myform" class="form-horizontal">
        <input type="text" class="form-control" name="name" ng-model="name" required="" validate  max-length="3"/>

         <div ng-show="myform.$submitted || myform.name.$touched" class="red">
                        <small ng-show="myform.name.$error.required" class="f-input-error f-700">Enter confirm password</small> 
                        <small ng-show="myform.name.$error.maxLength" class="f-input-error f-700">Max length 3</small>
                    </div>
      </form>
    </div>
  </document>
</body>

</html>

and Css

/* Styles go here */
.f-input-error
{
  color:red;
}

and my new plunker hope this helps https://plnkr.co/edit/YUwCvg6qr6M9mwAP3cqi?p=preview

Gayathri Mohan
  • 2,924
  • 4
  • 19
  • 25
  • hi, as you see in my demo plunker https://plnkr.co/edit/GAd9UdcHxCDyV6dH1Q7e?p=info , the validation 'maxlength' is injected inside the directive, the 'messages' are also injected inside the directive. In the html, I just have the input only , they are not static html code – khoailang Jun 09 '16 at 03:23
  • in your example, does it work if you strip out the max-length="3" and the whole
    – khoailang Jun 09 '16 at 03:42
  • its not a good practice to make in the Directive to hard code the error div. any way u have to active maxlength should work why cant you follow the the answer which i suggest – Gayathri Mohan Jun 09 '16 at 03:42
  • no no, I will not hardcode, let's talk about a scenario, a form would have a list of validation rules defined upfront in somewhere, they can be required, maxlength, ... or what ever or can be all kinds of them, I can use that definition to validate the form at client side (as exactly what the ng-messages does) or even server side – khoailang Jun 09 '16 at 03:52
  • your suggestion works, that is what the ng-message does. However, I am think by somehow we can automate that, with the ng-message we have to define the ' error message' for each single field – khoailang Jun 09 '16 at 03:56
  • or my approach might not be feasible – khoailang Jun 09 '16 at 03:57
0

Hi please check according to your requiremtn

var myapp = angular.module("myapp", ['ngMessages']);

myapp.controller("mycontroller", ['$scope', function($scope){
  $scope.name = 'hello';
}]);

myapp.directive('validate', ['$compile', function ($compile) {
    return {
        restrict: 'A',
         require: "ngModel",
        scope: {
               otherModelValue: "=validate"
             },
        replace: false,
        link: function(scope, element, attributes, ngModel) {

               ngModel.$validators.validate = function(modelValue) {
                   element.removeAttr("ng-required");
                element.attr("ng-required", "true");

                element.removeAttr("maxlength");
                element.attr("maxlength", "3");

              if(element.attr("maxlength") ==  modelValue.length)
              {

                var tpl = '<div id="divID"  ng-show = true >Max Length 3</div>' ;
                var el = $compile(tpl)(scope);
                element.after(el);
              }
              else
              {
                var myEl = angular.element( document.querySelector( '#divID' ) );
               myEl.empty();
              }
                 return modelValue == scope.otherModelValue;


               };

               scope.$watch("otherModelValue", function() {
                 ngModel.$validate();
               });
             }


    };
}]);

and HTMl

<!DOCTYPE html>
<html>

<head>
  <script src="https://code.angularjs.org/1.5.2/angular.js"></script>
  <script src="https://code.angularjs.org/1.5.2/angular-messages.js"></script>
  <link data-require="bootstrap-css@3.3.6" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>

</head>

<body>
  <document ng-app="myapp">
    <div ng-controller="mycontroller">
      <form name="myform" class="form-horizontal">
        <h1>{{myform.name.$error}}!</h1>
        <input type="text" class="form-control" name="name" ng-model="name" validate />
      </form>
    </div>
  </document>
</body>

</html>
Gayathri Mohan
  • 2,924
  • 4
  • 19
  • 25
  • thank you much, I like your approach, but I don't think I should use the $compile, that introduces performance issues. Even though your answer is not exactly what i need but that helps. I am considering to mark yours is the answer for my question. I also figure out my part, the point is that ng-messages is watching at 'form level' so I have to move the directive to "form" not field, my updated plunker https://plnkr.co/edit/GAd9UdcHxCDyV6dH1Q7e?p=preview – khoailang Jun 17 '16 at 12:50
  • your plunker doent work can u please check , any how u figured out thank u happy coding – Gayathri Mohan Jun 20 '16 at 01:29
  • the plunker is working, I don't have "ng-messages" in the static html but the directive add them runtime, once we got error message "required" or "maxlenght" then that is okay, I have not yet marked up the style :) – khoailang Jun 20 '16 at 06:58