Oskar Szura
Oskar Szura

Reputation: 2559

AngularJS dynamically added directives

I have the following

compile : function($scope, $element, $attrs, parentCtrl) {
    return {
        pre : function($scope, $element, $attrs, parentCtrl) {
            if($scope.feature == 'drop') {
                $element.find('.playlist').attr('droppable', true);
            }
        },
        post : function($scope, $element, $attrs, parentCtrl) {
            $scope.$parent.$watch('chosen', function(newAsset) {
                if(typeof newAsset != 'undefined' && newAsset.hasOwnProperty('id')) {
                    $scope.list.resource = newAsset.id;
                    $scope.list.loadData();
                }
            });
            }
        }
    }

now.... 'droppable' is a directive. But from what I can see - it's not being handled / compiled. If this is dymanically added within the 'compile-pre' should it be compiled by Angular?

How should I deal with dynamically generated directives?

Upvotes: 1

Views: 104

Answers (1)

Marc J. Schmidt
Marc J. Schmidt

Reputation: 8459

Adding new attributes or classnames do not re-trigger a new compile in AngularJS, neither in the compile step itself.

A working approach is to use terminal: true, choose a high priority, add new attributes in link and compile the element there again with a priority limit.

So, we have:

<my-directive></my-directive>

Our directive is defined like:

.directive('myDirective', ['$compile', function($compile) { return {
    priority: 1000,
    terminal: true,
    link: function(scope, element) {
        if (scope.feature) { 
           element.attr('droppable', true);
        }
        $compile($element, null, 1000)(scope);
    }
}}]);

What it does:

  • With priority: 1000 we say angular it should load this directive first (1000 is pretty high) if you let the 'droppable' directive have a default priority of 0.
  • With terminal: true we say angular to skip all directives on that element that comes after it (all with lower priority).
  • In link we add the new attribute to our current element dynamically which should trigger then a new directive in the next $compile step.
  • With $compile(element, transclude, maxPriority); it compiles the current element again, but only with directives that have priority < 1000, which means it excludes our myDirective directive and re-searches and applies all directives inclusive our newly added one.

Take a look at https://docs.angularjs.org/api/ng/service/$compile#-multielement- for more information here. It should jump directly to priority property (although the anchor is called the wrong, but angular's doc site is ... different).

Upvotes: 2

Related Questions