Search code examples
angularjsangularjs-ng-repeatangular-ui-bootstrapangularjs-ng-class

ng-class if else not working with repeat value


I been trying to change a class if a tab in a repeat, depending in the title of the tab. snippet shown below

 <tab ng-repeat="tab in tabs" heading="{{tab.title}}" ng-class="{{tab.title}} === 'Logs' ? 'pull-right' : ''" active="tab.active">
            <div class="col-md-12">
                <div ng-include="tab.content">
                </div>
            </div>
        </tab>

But it's not working. I tried changing the tab.title to $index.

<tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" ng-class="{{$index}} === 1 ? 'pull-right' : ''">
            <div class="col-md-12">
                <div ng-include="tab.content">
                </div>
            </div>
        </tab>

try with and without surrounding it with {} and {{}}. but still. nothing works.

Can anyone tell me what i'm doing wrong here?

as always, thanks for your time.

----EDIT---------

well i found a post where there was a workaround. don't know what happen. but it works. snippet shown below

              <tab ng-repeat="tab in tabs" heading="{{tab.title}}" active="tab.active" class="{{ tab.title == 'Logs' ? 'pull-right':'' }} ">
            <div class=" col-md-12">
            <div ng-include="tab.content">
            </div>


Solution

  • As said in the docs, value of ng-class is an expression that can be evaluated to a string, an object, or an array. That means you don't have to use {{}} there: simple...

    ng-class="tab.title === 'Logs' ? 'pull-right' : ''"
    

    ... should suffice. In fact, it's cleaner to write it as an object:

    ng-class="{'pull-right':tab.title === 'Logs'}"
    

    Sadly, that won't solve your case, as you're trying to apply ng-class to a custom directive (created with angular-ui Bootstrap package). That directive uses ng-class in its own template:

    <li ng-class="{active: active, disabled: disabled}">
      <a href ng-click="select()" tab-heading-transclude>{{heading}}</a>
    </li>
    

    ... and it's created with replace flag set to true. This effectively means value of ng-class supplied by you will be glued together with value supplied by template, resulting in something ugly like:

    <li ng-class="tab.title === 'Logs' ? 'pull-right' : '' {active: active, disabled: disabled}">
    

    That certainly won't work as planned. In fact, there's a related issue (#1741) registered at the project's hub - which is closed with the following commentary:

    Using ng-class on a directive that uses replace: true is a very bad idea. There are numerous issues around replace: true and even talk of deprecating/removing it. But, unfortunately, it's not going anywhere soon and the caveat released by the core Angular team was that use it, but do so at your peril. I.e., use it knowing that doing so incorrectly can break your DOM.

    I suspect this issue will not be addressed.

    One possible workaround is using native class with an Angular expression supplied as its value:

    class="{{tab.title === 'Logs' ? 'pull-right' : ''}}"
    

    This won't be merged with a <tab> template class, as there's no such thing there - and you're clear to go!