_
_
_ _2013-11-23 22:42:59
JavaScript
_ _, 2013-11-23 22:42:59

How to add directives on the fly in AngularJS?

I have a form, big enough.
There is an already worked out mechanism for displaying errors on the form, it is tied to the standard AngularJS validation + its own directive for displaying server validation errors.
Everything works, but there is one "but" - the html-code of the form after adding all these directives to the elements becomes a garbage heap. After all, you need to add ng-class everywhere in order to highlight the form element, and even cram a list of problems that arose with it under it.
I wanted to make a directive that would take data from an object in $scope and, based on the data in it, apply the necessary directives to form elements on the fly.
For example:

$scope.formSettings = {
     'required': ['title','description','date_from'],
     'server': ['title','description']
}

I made a directive that adds ngRequired to the element when linking, it even works. Looks something like this:
return app.directive('formControl', [
    '$compile', '$injector', function($compile, $injector) {
      return {
        priority: 0,
        require: '?ngModel',
        link: function($scope, element, attrs, controller) {
          var required;
          attrs.$set('ngRequired', "" + attrs.formControl + ".required('" + (element.attr('name')) + "')");
          required = $injector.get('requiredDirective')[0];
          return required.link($scope, element, attrs, controller);
        }
      };
    }
  ]);

The matter is that in such variant the expression set for ng-required is not processed - the element is always considered required.
How to be? I even looked through the AngularJS code, found the declaration of the directive, but I don’t understand how the expression from ngRequired is processed there, for the life of me.
I see what it's worth
attr.$observe('required', function() {
        validator(ctrl.$viewValue);
      });

AngularJS 1.2.2

Answer the question

In order to leave comments, you need to log in

2 answer(s)
_
_ _, 2013-11-24
@AMar4enko

Understood. If anyone is interested:
The point was, in fact, in the internals of angular, or rather, that when compiling a node, it forcibly checks for the presence of some attributes, and makes $scope.$watch for their content, inside which it does attrs.$set.
Since I added ngRequired after compiling the node, I just had to do something like:

$scope.$watch(attrs.formControl + ".required('" + (element.attr('name')) + "')", function(value){
    attrs.$set("required", !!value)
 });

And ngRequired, as shown above, keeps track of the value of the required attribute and updates the validation.

E
EugeneOZ, 2013-11-24
@EugeneOZ

After changing the composition of attributes and / or directives, you need to recompile the element (call compile on it).

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question