AngularJS 多次使用相同的指令元素(验证错误)

AngularJS using same directive element multiple times (Validation error)

我准备了一个表单,其中一个表单有 2 个指令元素。 但是第一个的验证不起作用,第二个的验证错误出现在两个指令元素上。

我该如何解决这个问题? 下面给出了 plunk 项目 link。

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>

输入-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

感谢您的回答。

根据您的 plunker,我做了一些可以帮助您的更改。

index.html

<input-email name='email1' ng-model="person.email1" required></input-email>
<input-email name='email2' 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': !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>

输入邮箱

...
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);
            });
...

希望对您有所帮助

写在这里以防有人遇到同样的问题:

我在遗留项目中工作,目前正在将 AngularJS 版本从 1.3.x 更新到 1.8.x。突然之间,使用具有相同指令属性的多个元素不再有效。所有元素中只显示了一个,其余元素神​​奇地消失了,没有任何错误消息或其他痕迹。

我有三个使用指令的元素:

<div select-person person="one" />

<div select-person person="two" />

<div select-person person="three" />

我的指令控制器与此类似:

  angular
    .module('demo')
    .directive('selectPerson', ['customSettings', selectDirective]);

  function selectPersonDirective(customSettings) {
    return {
      templateUrl: "Directives/SelectDirective",
      scope: {
        person: '@'
      },
      bindToController: true,
      controller: selectCtrl,
      controllerAs: 'ctrl'
    };

function selectCtrl() {
   ...
}

问题是只显示了 一个 使用指令的元素。在阅读了 Whosebug 上的每一页以及完整的 AngularJS 文档后,我尝试了指令中的所有可能更改,因为我认为范围隔离存在问题。

在头痛了几天之后,我终于设法解决了我的问题:

我在指令元素上有一个自封闭的 HTML 标签,而不是“正常”关闭它:

<div select-person person="one"></div>

<div select-person person="two"></div>

<div select-person person="three"></div>

在此之后,我的代码又神奇地开始正常工作了。