5

AngularJS supports multi-element directive with -start and -end postfix. The official documentation only mentions ng-repeat-start and ng-repeat-end. Do other built-in directives support this?

For example, this works fine:

<tbody>
  <tr ng-controller="myController">
    <td>{{firstName}}</td>
    <td>{{lastName}}</td>
  </tr>
</tbody>

Both {{firstName}} and {{lastName}} are replaced with their proper value.

But this only works partially:

<tbody>
  <tr ng-controller-start="myController">
    <td>{{firstName}}</td>
  </tr>
  <tr ng-controller-end>
    <td>{{lastName}}</td>
  </tr>
</tbody>

{{firstName}} is properly replaced. But {{lastName}} is empty. Since {{firstName}} works, seems ng-controller-start is recognized by AngularJS. Is it a bug, or I'm doing it wrong, that {{lastName}} is not working?

Update If ng-controller-start and ng-controller-end is not officially supported. How do I make ng-controller to span multiple elements? Can I use comment-style directive? If yes, how?

3
  • Pretty sure that this is unique to ng-repeat: code.angularjs.org/1.2.21/docs/api/ng/directive/ngRepeat Commented Aug 11, 2014 at 23:43
  • I think it may be half-baked feature for other directives. When I remove ng-controller-end, AngularJS throws an exception saying "no matching ng-controller-end found for ng-controller-start", so it definitely understands ng-controller-start. Commented Aug 12, 2014 at 0:18
  • @ExplosionPills That's not, but using it with ngController is kinda strange. Commented Aug 12, 2014 at 0:19

2 Answers 2

4

Whether or not a directive supports this is based on its directive definition and the multiElement property.

It doesn't seem like Angular's documentation says which built in directives are multi-element, but a Github search seems to reveal that it's only ngRepeat, ngSwitchWhen, ngSwitchDefault, ngIf, ngShow, and ngHide.

You can create your own directives with multiElement as well.

Sign up to request clarification or add additional context in comments.

Comments

4

In Angular 1.2

With Angular 1.2, support for multi-element directives was introduced. It seems like the specific use-case they had in mind was ngRepeat, since it wasn't promoted to be used with any of the other built-in directives as far as I am aware. With ngRepeat, however, it solved a very particular problem such as how to repeat more than one table row per item.

In 1.2, the $compile service will detect any directive that is suffixed with -start and assume it to be one of a pair of multi-element directive attributes (source). This leads to the undesirable side-effect that you cannot name your directive something-start, as the $compile service will get confused when it does not find the multi-element counterpart.

This leads to the error: Error: [$compile:uterdir] Unterminated attribute, found 'something-start' but no matching 'something-end' found.

The fact that the $compile service is indiscriminate in treating directives as multi-element is why you are able to use ng-controller-start and ng-controller-end in Angular 1.2. However the ngController directive is not designed to deal with multiple elements and this is why it does not work as expected. It will act on the first element in the range, and ignore the rest - just as you observed.

In Angular 1.3

Angular 1.3 fixes the above problem by requiring that any multi-element directives be explicitly defined as such by using the new multiElement: true property on the directive definition object. See the docs on this

This means that ng-controller-start will not do anything in 1.3, since it will cause the compiler to look for a directive named "ngControllerStart", which does not exist. Therefore the directive attribute will simply be ignored.

As the other answer points out, you can now search the angular.js GitHub repo for "multiElement" to see the specific core directives that support this feature.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.