AngularJS change order of which directives are compiled

Viewed 8162

As far as I've noticed Angular compiles things on a first come, first-serve basis which is kind of tricky. I made a directive which wraps some elements around and I want to have a link property which looks for stuff in the content.

For a concrete use-case: I am making a input label directive which looks inside the content for the first input and adds a randomly generated id to the input and a for attribute to the label

Here's the code:

// Find the first element with the attribute ng-label-target or the first input and links a label to it
app.directive('ngLabel', function () {
  return {
    restrict: 'E',
    replace: true,
    transclude: true,
    scope: {
      label: '@',
    },
    template: '<span class="ng-label">' +
                '<label class="ng-label-text">{{label}}</label>' +
                '<span class="ng-label-content" ng-transclude></span>' +
              '</span>',
    link: function (scope, element, attrs) {
      scope.id = scope.id || 'random-id-' + Math.floor(Math.random() * 90000000);
      angular.element(element[0].querySelector('.ng-label-text')).
        attr({for:scope.id});

      var target = angular.element(element[0].querySelector('[ng-label-target]'));
      if (!target || target.length == 0) {
        target = angular.element(element[0].querySelectorAll('input,select,textarea')[0]);
      }
      target.attr({id:scope.id});
    },
  };
});

Example Usage:

<ng-label label="Text:">
   <input type="text" ng-model="page.textColor" size="5" maxlength="7" placeholder="e.g. #000" required />
   <input ng-label-target type="color" ng-model="page.textColor" required />
</ng-label>

This by itself works like a charm.

However now I want to auto-generate several inputs and have the label point to the first one. The issue is that when I do a ng-repeat inside my ng-label then ng-repeat code gets generated after my directive was processed so nothing actually gets found.

Therefore my question is: is there a way in which you can specify to angular to evaluate nested directives inside out instead of the other-way around?

Or, is there a batter way of doing this than I'm currently doing?

I made a fiddle to exemplify the order in which stuff gets evaluated. You see that the outer-directive has a smaller or equal value than it's contents (can't go lower than microseconds so I had to do a bunch of repeats):

http://jsfiddle.net/YLM9P/

4 Answers
Related