Angularjs: form validation and input directive

16,793

Try my dynamic-name directive here: AngularJS dynamic form field validation

Replace name="{{opts.inputname}}" with dynamic-name="opts.inputname"

I also simplified your code for demonstration:

app.directive("dynamicName", function($compile) {
  return {
    restrict: "A",
    terminal: true,
    priority: 1000,
    link: function(scope, element, attrs) {
      var name = scope.$eval(attrs.dynamicName);
      if (name) {
        element.attr('name', name);
        element.removeAttr("dynamic-name");
        $compile(element)(scope);
      }
    }
  };
});

app.directive('formInput', function($compile) {
  return {
    replace: true,
    scope: {},
    templateUrl: 'formInput.html',
    restrict: 'E',
    link: function(scope, element, attrs) {
      scope.opts = attrs;


      $compile(element.contents())(scope);
    }
  }
});

Form Input template:

<label class="acxm-textfield {{opts.cssclass}}">
  <span ng-bind="opts.labeltext"></span>
  <input type="{{opts.type}}" dynamic-name="opts.inputname" ng-model="opts.inputvalue"
  placeholder="{{opts.placeholder}}" 
  ng-maxlength="{{opts.maxLength}}" required/> //use dynamic-name directive to bind dynamic names.
</label>

DEMO (try clearing the text to see the validation, I used required validation for quick demonstration, you could change the code to email validation). The key is using the dynamic-name directive.

Share:
16,793
Adrian Wajs
Author by

Adrian Wajs

Updated on June 09, 2022

Comments

  • Adrian Wajs
    Adrian Wajs almost 2 years

    I created a directive in an AngularJS app which produces styled input in my application. It looks like this:

    AC.directive('formInput',function ($compile) {
        return {
            transclude: true,
            replace: true,
            scope:{},
            templateUrl: '/views/partials/form/input.html',
            restrict: 'E',
            link: function(scope, element, attrs){
    
                scope.opts = attrs;
    
                if(attrs.ngModel){
                    element.find('input').attr('ng-model', attrs.ngModel);
                    $compile(element.contents())(scope.$parent);
                }
    
                if(!attrs.type){
                    scope.opts.type = 'text';
                }
            }
        };
      }
    )
    

    And the template for it is:

    <label class="acxm-textfield {{opts.cssclass}}">
      <span ng-bind="opts.labeltext"></span>
      <input type="{{opts.type}}" name="{{opts.inputname}}" value="{{opts.inputvalue}}" placeholder="{{opts.placeholder}}" ng-maxlength="{{opts.maxLength}}"/>
    </label>
    

    The call is simple:

    <form-input ng-model="UserProfile.FirstName" max-length="50" labeltext="{{'GENERAL.name' | translate}}" cssclass="acxm-p-horizontal" inputname="name" inputvalue="{{UserProfile.FirstName}}"></form-input>
    

    I wanted to create validation for this field and I added an error information:

    <span ng-show="showError(userInfoForm.name,'email')">
                        You must enter a valid email
    </span>
    

    And showError is:

    $scope.showError = function(ngModelController, error) {
    
        return ngModelController.$error[error];
    };
    

    Basically, it is copied from the book "Mastering Web Application Development with AngularJS". I have a problem because when I log my form, which name is userInfoForm, in console I got {{opts.inputname}} instead of name property which value here should be "name". What am I doing wrong?