【问题标题】:AngularJS - Create a directive that adds a sibling elementAngularJS - 创建一个添加同级元素的指令
【发布时间】:2013-06-05 14:20:13
【问题描述】:

我正在创建一个看起来像这样的my-validate 指令

<input my-validate="customValidation" ng-model="model" />

我想做的是像这样将一个sybling元素附加到指令中

错误模板:

<ul class"errors">
   <li ng-repeat="for error in errors">{{error}} not valid</li>
</ul> 

errors 在指令范围内定义。

我已经在compile函数中添加了错误模板,但是我遇到的问题是链接函数中的scope与附加的模板不一样。

这里有一个 plunker 来说明这个问题:http://plnkr.co/edit/ghdtdYruQaaO0Yxxlrt1?p=preview

'world' 出现在指令模板中,但没有出现在添加的元素 :S 上。

【问题讨论】:

  • plunker 链接与问题无关。我假设你已经覆盖了它?请解决这个问题。

标签: angularjs angularjs-directive


【解决方案1】:

那是因为您的 div "2 hello" 在您的范围可见的容器之外。 您可以使用 element.append() 而不是 element.after() 来获得可用的范围。

指令

var app = angular.module('plunker', []);


app.directive('myValidate', function($compile) {
      return {
        template: '<span>1. Hello {{world}}  my scope is {{$id}} (parent: {{$parent.$id}})<span/>',
        replace: true,
        restrict: 'A',
        scope: true,
        compile: function (element) {

          element.append('<div>2. Hello {{ world }}, my scope is {{$id}} (parent: {{$parent.$id}})</div>');

          return function(scope) {
            scope.world = 'World';
            //$compile()(scope);
          };
        }
      };
});

HTML

<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script data-require="angular.js@1.1.5" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="app.js"></script>
  </head>

  <body>
    <input my-validate="" />
  </body>

</html>

http://plnkr.co/edit/dU3holBCePKe0ZAwQKh1?p=preview

【讨论】:

【解决方案2】:

我正在阅读并检查该示例,因为我在相同的情况下显示验证消息,但输入字段下,并且消息可以根据需要的验证类型进行更改。

所以我想出了这个解决方案

var app = angular.module('app', []);

app.controller('ctrl', function($scope, CONSTANTS) {
  $scope.title = "title";
  $scope.CONSTANTS = CONSTANTS;
});

app.constant('CONSTANTS', {
  LENGHT_1: 3,
  LENGHT_2: 4
});

app.directive('dir', function($compile) {
  return {
    scope: true,
    restrict: 'A',
    require: '?ngModel',
    link: function(scope, elem, attrs, ngModel) {
      scope.maxLength = false;
      scope.required = false;
      scope.max = scope.$eval(attrs['ngMaxlength']);
      var tpl = '<div ng-if="maxLength" ng-include="\'length.tpl.html\'"></div>' +
        '<div ng-if="required" ng-include="\'required.tpl.html\'"></div>';
      var el = $compile(tpl)(scope);
      elem.after(el);

      scope.$watch(attrs['ngModel'], function(newValue, oldValue, scope) {
        if (ngModel.$error !== null && ngModel.$error.maxlength) {
          scope.maxLength = true;
        } else {
          scope.maxLength = false;
        }

        if (ngModel.$error !== null && ngModel.$error.required && ngModel.$dirty) {
          scope.required = true;
        } else {
          scope.required = false;
        }
      });
    }
  }
});
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script data-require="angular.js@1.4.7" data-semver="1.4.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
  
  <script type="text/ng-template" id="length.tpl.html">
    max length {{max}}
  </script>
  <script type="text/ng-template" id="required.tpl.html">
    required
  </script>
</head>

<body ng-controller="ctrl">
  <h1>Input Validation</h1> {{title}}
  <br><br>
  <form name="form" novalidate>
    <input dir name="input_one" ng-model="bar" ng-maxlength="CONSTANTS.LENGHT_1" required>
    <br>
    input one: {{form.input_one.$error}}
    <br>
    <br>
    <input dir name="input_two" ng-model="foo" ng-maxlength="CONSTANTS.LENGHT_2">
  </form>
  <br>
  input two: {{form.input_two.$error}}
</body>

</html>

On Plunkr

希望对你有帮助。

【讨论】:

  • 这确实有效,这很好,但是如果能够为整个兄弟集合指定一个整体模板,而不是依赖于 JS 端的 DOM 操作,那就太好了追加、前置或其他。
【解决方案3】:

我认为通过使用表单错误来切换显示,您走在了正确的轨道上。这正是标准 Angular 文档中推荐的方式。

但是,如果您想为单个输入显示多个错误,甚至可能从那里控制错误消息,我建议您使用服务,例如在 http://plnkr.co/edit/iNcNs2ErrOnYf9I7whdu?p=preview 实现的服务。

现在每个令牌可以有一条消息,但每个输入可以有任意多个令牌。如果您希望每个令牌多条消息,只需使用消息数组而不是单个字符串值(注意,使用该方法 unset 确实变得更加复杂)。

希望对您有所帮助, 亚历克斯

【讨论】:

  • 这并没有解决问题。
猜你喜欢
  • 2015-03-14
  • 2014-03-21
  • 1970-01-01
  • 2014-04-02
  • 1970-01-01
  • 1970-01-01
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多