Search code examples
angularjsemailangularjs-directivemultiple-instances

AngularJS using same directive element multiple times (Validation error)


I have prepared a form that have 2 directive elements in one form. But the first one's validation does not work and second one's validation errors appear on both directive element.

How can I overcome this issue? The plunk project is on given link below.

Click for the Plunker Project

index.html

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <title>Durakhan</title>
    <!--[if lt IE 9]>
            <script src="//html5shim.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
    <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js"></script>
    <script>
      var app = angular.module('app', []);
      app.controller('AppCtrl', ['$scope',function($scope) {
      $scope.person = {};
    }]);
  </script>
</head>
<body ng-controller="AppCtrl">
    <script src="inputEmail.js"></script>
    <script src="InputEmailCtrl.js"></script>
    <div id="Div1" class="modal" tabindex="-1" style="display: block" role="dialog" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-body">
                    <form class="form col-md-12 center-block" name="loginForm"  novalidate>
                        <input-identityemail ng-model="person.identityemail"></input-identityemail>
                        <input-email ng-model="person.email1" required></input-email>
                        <input-email ng-model="person.email2" required></input-email>
                        <label class="col-sm-2 control-label">Email</label>
                        <div class="col-sm-4" ng-class="{'has-error': loginForm.email3.$invalid}">
                          <input type="email" name="email3" ng-model="person.email3" class="form-control" ng-required="required">
                          <span ng-show="loginForm.email3.$error.required" class="help-block">Can't be blank</span>
                          <span ng-show="loginForm.email3.$error.email" class="help-block">Not a valid email</span>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    Person: <pre>{{person | json}}</pre>
                    Form $error: <pre>{{loginForm.$error | json}}</pre>
                    <p>Is the form valid?: {{loginForm.$valid}}</p>
                    <p>Is 1st email valid?: {{loginForm.email1.$valid}}</p>
                    <p>Is 2nd email valid?: {{loginForm.email2.$valid}}</p>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

input-email.html

<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-4" ng-class="{'has-error': form.email.$invalid}">
  <input type="email" name="email" ng-model="email" class="form-control" ng-required="required">

  <span ng-show="form.email.$error.required" class="help-block">Can't be blank</span>
  <span ng-show="form.email.$error.email" class="help-block">Not a valid email</span>
</div>

inputEmail.js

'use strict';

app.directive('inputEmail', function () {
    return {
        restrict: 'E',
        templateUrl: 'input-email.html',
        replace: false,
        controller: 'InputEmailCtrl',
        require: ['^form', 'ngModel'],

        // See Isolating the Scope of a Directive http://docs.angularjs.org/guide/directive#isolating-the-scope-of-a-directive
        scope: {},

        link: function (scope, element, attrs, ctrls) {
            scope.form = ctrls[0];
            var ngModel = ctrls[1];

            if (attrs.required !== undefined) {
                // If attribute required exists
                // ng-required takes a boolean
                scope.required = true;
            }

            scope.$watch('email', function () {
                ngModel.$setViewValue(scope.email);
            });
        }
    };
});

inputEmailCtrl

'use strict';

app.controller('InputEmailCtrl', ['$scope', function ($scope) {
}]);

Click for the Plunker Project

thanks for answers.


Solution

  • Based in your plunker I made some changes that could help you.

    index.html

    <input-email name='email1' ng-model="person.email1" required></input-email>
    <input-email name='email2' ng-model="person.email2" required></input-email>
    

    input-email

    <label class="col-sm-2 control-label">Email</label>
    <div class="col-sm-4" ng-class="{'has-error': !form.{{varName}}.dirty && form.{{varName}}.$invalid}">
          <input type="email" name="varName" ng-model="varModel" class="form-control" required>
    
          <span ng-show="form.{{varName}}.$error.required" class="help-block">Can't be blank</span>
          <span ng-show="form.{{varName}}.$modelValue == undefined" class="help-block">Not a valid email</span>
    </div>
    

    inputEmail

    ...
    scope: {
              varModel: '=ngModel',
              varName: '@name'
            },
    
            link: function (scope, element, attrs, ctrls) {
                scope.form = ctrls[0];
                var ngModel = ctrls[1];
    
                if (attrs.required !== undefined) {
                    // If attribute required exists
                    // ng-required takes a boolean
                    scope.required = true;
                }
    
                scope.$watch(scope.varModel, function () {
                    ngModel.$setViewValue(scope.varModel);
                });
    ...
    

    Hope this help