admin管理员组

文章数量:1291009

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 ment-style directive? If yes, how?

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 ment-style directive? If yes, how?

Share Improve this question edited Sep 29, 2015 at 15:14 rave 1,0322 gold badges12 silver badges23 bronze badges asked Aug 11, 2014 at 23:39 cnshenjcnshenj 1672 gold badges3 silver badges10 bronze badges 3
  • Pretty sure that this is unique to ng-repeat: code.angularjs/1.2.21/docs/api/ng/directive/ngRepeat – Explosion Pills 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. – cnshenj Commented Aug 12, 2014 at 0:18
  • @ExplosionPills That's not, but using it with ngController is kinda strange. – Blackhole Commented Aug 12, 2014 at 0:19
Add a ment  | 

2 Answers 2

Reset to default 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.

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 $pile 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 $pile service will get confused when it does not find the multi-element counterpart.

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

The fact that the $pile 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 piler 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.

本文标签: javascriptAngularJS multielement directiveStack Overflow