验证嵌套在另一个指令中的自定义选择指令

时间:2015-12-17 14:47:41

标签: javascript angularjs angularjs-directive

我有2个指令:my-custom-formmy-custom-select。如何在my-custom-form指令中嵌套my-custom-select指令触发自定义验证?

Plunker http://plnkr.co/edit/PJIL8T2Fj1i4Fw4dyPjR?p=preview

my-custom-form指令用法:

<div ng-controller="MyExampleCtrl as exampleCtrl">
  <my-custom-form form-name="exampleForm" form-submit="exampleCtrl.submit()"></my-custom-form> 
</div>

my-custom-form指令

angular.module('myApp')
  .directive('myCustomForm', [function() {

    var link = function(scope, element, attrs, ctrls) {
      var formCtrl = ctrls[0];
      var thisDirectiveCtrl = ctrls[1];

      scope.submitMyForm = function() {
         if (formCtrl.$valid) {
           //submit form
           thisDirectiveCtrl.submit();
         }
      };

      // Show some inline validation
      scope.hasError = function(field) {
        var isInvalidandSubmitted = scope.submitted && formCtrl[field].$invalid;
        var isInvalidandDirty = formCtrl[field].$invalid && formCtrl[field].$touched && !formCtrl[field].$pristine;

        return isInvalidandSubmitted || isInvalidandDirty; 
      };
    };

    var controller = function($scope, $element, $attrs) {
      var vm = this;

      // this is the form model
      vm.data = {};

      // this executes the submit function from the parent controller (MyExampleCtrl)
      vm.submit = function() {
       vm.formSubmit();
      };
    };

    return {
      restrict: 'E',
      replace: true,
      transclude: true,
      templateUrl: 'templates/my-custom-form-template.html',
      scope: {
        formName: '@',
        formSubmit: '&'
      },
      require: ['form', 'myCustomForm'],
      link: link,
      controller: controller,
      controllerAs: 'myCustomFormCtrl',
      bindToController: true
    };
  }]);

在my-custom-form-template.html

<form name="{{formName}}" novalidate>
  <div class="form-group" ng-class="{ 'is-invalid': hasError('firstName')}">
    <input type="text" ng-model="myCustomFormCtrl.data.firstName" name="firstName" required />
    <p ng-show="hasError('firstName')">Enter a first name.</p>
  </div>

  <div class="form-group">
    <!-- Nested directive here -->
    <div class="form-group">
      <my-custom-select ng-model="myCustomFormCtrl.data.country" name="country" required></my-custom-select>
    </div>

  </div>
  <button type="button" ng-click="submitMyForm()">Submit</button>
</form>

自定义选择指令

angular.module('myApp')
  .directive('myCustomSelect', ['DataService', function(DataService) {

    return {
      restrict: 'E',
      replace: true,
      require: '^?myCustomForm',
      templateUrl: 'templates/my-custom-select-template.html',
      scope: {
        name: '@',
        ngModel: '=',
        required: '='
      },
      link: function(scope, el, attrs, parentCtrl) {
        scope.countries = [];

        // Set required attribute
        if (scope.required) {
          el.find('select').attr('required', true);
        }

        // call out to external service and populate select
        DataService.get().then(function(res) {
          scope.countries = res;
        });

        // How can I trigger validation?
      }
    };

  }]);

在自定义选择模板中:

<div class="select">
  <select ng-model="ngModel" name="{{name}}" ng-change="updateSelect()">
    <option value="" disabled>Select option</option>
    <option ng-repeat="country in countries" value="{{country.code">{{country.name}}</option>
  </select>

  <!-- how can I do something like this ? -->
  <div ng-if="required">
     <p ng-show="hasError('country')">Please select a</p>
  </div>
</div>

2 个答案:

答案 0 :(得分:0)

在这种情况下你可以使用 ngForm指令

它实例化一个FormController,并允许您访问每个输入或选择子元素。

答案 1 :(得分:0)

ng-form 解决了在调用子指令时验证嵌套指令的问题,使用的ng-form属性与创建子表单时给出的表单名称相同。

  

儿童指令表

 <form name="bankAccountForm">
   ....html.....
 </form>
  

家长指令表

<form name="customerContractingEntityForm" ng-submit="saveCustomer()" novalidate>

  ............ parent HTML........

    <div ng-form="bankAccountForm">    //// this live validates the child directive
        <div ws-bank-account></div>    //// calling child direcive here
    </div>                
</form>