intrinsiciwnl intrinsiciwnl - 1 year ago 140
AngularJS Question

Angular/Bootstrap data-target not evaluating expression

I have in my jade/pug file:

div(ng-repeat='writing in user.clean_profile.writing_samples track by $index')
a(toggle target="collapse" data-target="{{\'#collapse\'+$index+1}}") Link {{$index+1}}
iframe.collapse(id="collapse{{$index+1}}" toggleable ng-src='{{preview(writing.url)}}', frameborder='0' )


<div ng-repeat="writing in user.clean_profile.writing_samples track by $index">
<a toggle="toggle" target="collapse" data-target="{{'#collapse'+$index+1}}">Link {{$index+1}}</a>
<iframe id="collapse{{$index+1}}" toggleable="toggleable" ng-src="{{preview(writing.url)}}" frameborder="0" class="collapse"></iframe>

However, the link is not evaluating correctly: the actual html data-target element evaluates to {{'#collapse'+$index+1}} instead of 0,1,2, etc.

Any ideas?

Answer Source

If the element has already been assigned a value to the attribute something, the binding to the data-something after that will not work and vice versa.

So you need change either the target attribute or the data-target to enable the binding. Or put the binding one before the not binding one.

The reason for this issue in in the way angular creates the attributes map of an element.

In the source code of angular complie.js around line 2081:

        nName = directiveNormalize(name.toLowerCase());
        attrsMap[nName] = name;
        if (isNgAttr || !attrs.hasOwnProperty(nName)) {
            attrs[nName] = value;
            if (getBooleanAttrName(node, nName)) {
              attrs[nName] = true; // presence means true

Here isNgAttr is the value holding whether the current processing attribute is an attribute with ng- prefix.

The directiveNormalize function will eliminate the 'data-' prefix of attribute.

So now the data-something and something share the same name in the element's attribute map.

By the code above, the attribute's value in attrs will always keep the FIRST ONE of these two.