AngularJS - Create a directive that adds a sibling element

◇◆丶佛笑我妖孽 提交于 2019-12-05 12:11:24
Eduard Gamonal

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

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.

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

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