AngularJS自定义指令类似于ng-requried

时间:2015-09-04 20:31:06

标签: javascript angularjs

所以我已经花了大约4个小时。
我想要实现的是一个类似于ng-required的自定义指令,它有一个输入并进行验证。
以下是ng-required代码。

var requiredDirective = function() {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elm, attr, ctrl) {
      if (!ctrl) return;
      attr.required = true; // force truthy in case we are on non input element

      ctrl.$validators.required = function(modelValue, viewValue) {
        return !attr.required || !ctrl.$isEmpty(viewValue);
      };

      attr.$observe('required', function() {
        ctrl.$validate();
      });
    }
  };
};

我知道当所需属性更改其值时,我们会再次进行验证。假设你有

<input 
ng-model="sor.seal"
ng-model-options="{ updateOn : 'default blur' }"
class="form-control" 
ng-required="sor.sealUwatType=='SEAL'" 
type="text"
placeholder="Enter a SEAL/UWAT ID"
id="seal" 
name="seal" 
/>

当ng-required表达式为真时,如何添加属性 required =&#34; required&#34; ? 当ng-required表达式为false时,它如何删除属性?

1 个答案:

答案 0 :(得分:1)

Angular在所有布尔属性等价上创建内部ng-attribute Alias directive,如ng-required, ng-checked, ng-disabled等...

<强> Source

var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
  BOOLEAN_ATTR[lowercase(value)] = value;
});

并且在这些上注册的通用链接函数执行属性的通用切换

<强> Source

forEach(BOOLEAN_ATTR, function(propName, attrName) {
  // binding to multiple is not supported
  if (propName == "multiple") return;

  function defaultLinkFn(scope, element, attr) {
    scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
      attr.$set(attrName, !!value);
    });
  }

  var normalized = directiveNormalize('ng-' + attrName);
  var linkFn = defaultLinkFn;

  if (propName === 'checked') {
    linkFn = function(scope, element, attr) {
      // ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
      if (attr.ngModel !== attr[normalized]) {
        defaultLinkFn(scope, element, attr);
      }
    };
  }

  ngAttributeAliasDirectives[normalized] = function() {
    return {
      restrict: 'A',
      priority: 100,
      link: linkFn
    };
  };
});

所以基本上ng-required添加了which itself is registered internally as a directiverequired validation for ng-model属性。

您可以通过输出实际拥有的ngRequired指令来验证这一点,它包含2个指令配置,一个优先级为100(在ng-model之前运行),它设置/重置其所在元素的属性另一个具有ng-model和验证器的验证钩子。

.config(function($provide) {
  $provide.decorator('ngRequiredDirective', function($delegate) {
    console.log($delegate); //Check the console on the configuration you will see array of 2 configurations
    return $delegate;
  })
});

这与为同一指令选择器创建2个配置一样好,例如:

&#13;
&#13;
angular.module('app', []).directive('myDir', function() {
  return {
    restrict: 'A',
    link: function() {
      console.log("A");
    }
  }
}).directive('myDir', function() {
  return {
    restrict: 'A',
    link: function() {
      console.log("B");
    }
  }
}).config(function($provide) {
  $provide.decorator('myDirDirective', function($delegate) {
    console.log($delegate); //Check the console on the configuration you will see array of 2 configurations
    return $delegate;
  })
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<div ng-app="app">

  <div my-dir></div>
</div>
&#13;
&#13;
&#13;