AngularJS - Create a directive that adds a sibling element

可紊 提交于 2019-12-10 09:35:24

问题


I'm creating a my-validate directive that looks something like this

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

What I want to do is to attach a sybling element to the directive like this

Error template:

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

errors is defined in the scope of the directive.

I've added the error template in the compile function, but the problem I have is that the scope in the link function is not the same as the attached template.

Here is a plunker to illustrate the issue: http://plnkr.co/edit/ghdtdYruQaaO0Yxxlrt1?p=preview

'world' is seen in the directive template, but not on the added element :S.


回答1:


That's because your div "2 hello" is outside the container where your scope is visible. you can use element.append() instead of element.after() to have the scope available.

Directive

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:


I was reading and checking the example because I was in the same situation to display validation messages but under the input field and the message can change according to what kind of validation is required.

So I came up with this solution

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

Hope it helps.




回答3:


I think you're on the right track by using the form errors to toggle display. That's exactly how it's recommended in the standard Angular documentation.

If you'd like to show multiple errors for a single input, however, and possible even control the error messages from there, I'd recommend utilizing a service, such as implemented at http://plnkr.co/edit/iNcNs2ErrOnYf9I7whdu?p=preview.

Right now you can have one message per token, but as many tokens as you want per input. If you want multiple messages per token, just use an array of messages instead of single string value (note, unset does become more complicated with that method).

Hope that helps, Alex



来源:https://stackoverflow.com/questions/16942419/angularjs-create-a-directive-that-adds-a-sibling-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!