1

I'm doing a web app with Angular which contains a table with a collapsable tr. But when I add some ng-if condition (if there are / are not data in the Array)the ng-show stops to work. This is the working code without the ng-if conditions: https://plnkr.co/edit/UPFF1RboN22RAVM8r18i?p=preview

      <thead>
    <tr role="row">
      <th class="details-control sorting_disabled" rowspan="1" colspan="1" aria-label="" style="width: 26px;">
        <th class="sorting_asc" tabindex="0" aria-controls="example" rowspan="1" colspan="1" aria-label="Projects: activate to sort column descending" aria-sort="ascending" style="width: 306px;">Foods</th>
        <th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" aria-label=" EST: activate to sort column ascending" style="width: 84px;"><i class="fa fa-fw fa-user text-muted hidden-md hidden-sm hidden-xs"></i> Type</th>
        <th class="sorting" tabindex="0" aria-controls="example" rowspan="1" colspan="1" aria-label="Contacts: activate to sort column ascending" style="width: 107px;">Count</th>
    </tr>
  </thead>

<tbody ng-repeat="data in allData" >
  <tr>
      <td>
          <div class="cursor-pointer" ng-click="rows = !rows">
              <!-- <span class="fa" ng-class="{'fa-caret-down': rows, 'fa-caret-right': !rows}"></span> -->
              <p>open</p>
          </div>
      </td>
      <td>{{data.foodName}}</td>
      <td></td>
      <td>{{data.totalCount}}</td>
  </tr>
    <tr ng-repeat="a in data.avaiable" ng-show="rows" ng-if="allData && allData.length > 0">
      <td></td>
      <td></td>
      <td>{{a.foodType}}</td>
      <td>{{a.foodCount}}</td>
  </tr>

This is the not-working code with the ng-if conditions. If you see at the plk https://plnkr.co/edit/IvlIXIfWpogNi5VXo2Eh?p=preview you can notice that the rows doesn't show. Why?

panagulis72
  • 2,129
  • 6
  • 31
  • 71

4 Answers4

3

Cosmin is right.

ng-if creates a new child scope.

you have to use $parent to use parent variable which you are using inside ng-if

change you ng-click to :

ng-click="$parent.rows = !rows"

working Plunker

To display No Data Found use other body in you table

<tbody ng-repeat="data in allData" >
  <tr ng-if="allData && allData.length > 0">
      <td>
          <div class="cursor-pointer" ng-click="$parent.rows = !rows">
              <!-- <span class="fa" ng-class="{'fa-caret-down': rows, 'fa-caret-right': !rows}"></span> -->
              <p>open</p>
          </div>
      </td>
      <td>{{data.foodName}}</td>
      <td></td>
      <td>{{data.totalCount}}</td>
  </tr>
    <tr ng-repeat="a in data.avaiable" ng-show="rows" ng-if="allData && allData.length > 0">
      <td></td>
      <td></td>
      <td>{{a.foodType}}</td>
      <td>{{a.foodCount}}</td>
  </tr>
  </tbody>

<!-- If there are no data -->
  <tbody ng-if="allData && (allData == null || allData.length == 0)">
       <tr>
           <td colspan="3"><span translate="generic.NO_DATA_FOUND">NO DATA FOUND</span></td>
       </tr>
  </tbody>
gaurav bhavsar
  • 2,033
  • 2
  • 22
  • 36
2

As per the understanding of your requirement if you just replace the code

ng-click="rows = !rows" with ng-click="data.rows = !data.rows"

and

ng-show="rows" with ng-show="data.rows"

it must work

Harpreet
  • 1,527
  • 13
  • 25
1

The reason why it doesn't work is that ng-if creates a new child scope thus breaking the prototypical scope inheritance.

Must reads in order to better understand this issue:

As a good rule of thumb, always use controller as syntax. Here's why you should use it.

A quick fix for you would be to access the rows property from another object like this: ng-show="container.rows" - this way you won't break the prototypical scope inheritance. See an working example here.

Community
  • 1
  • 1
Cosmin Ababei
  • 7,003
  • 2
  • 20
  • 34
  • Thank you @cosmin! But I didn't understand very well you quick fix – panagulis72 Mar 23 '16 at 09:25
  • I've switched to the **quick fix** solution in which I bind the `rows` property to `data` like this: `data.rows`. You can see it working [here](https://plnkr.co/edit/5tLOs3keUg1PbbcCepR3?p=preview). – Cosmin Ababei Mar 23 '16 at 09:45
0

If you need to check has data or not in allData and based on allData want to use ng-repeat then use ng-if condition in same element

<tbody ng-if="allData && allData.length > 0" ng-repeat="data in allData" >

instead of nested element <tr ng-if="allData && allData.length > 0">

And better to use data.rows instead of rows in ng-click to set and in ng-show to show specific data rows. like: ng-click="data.rows = !data.rows" and ng-show="data.rows"

Total solution can be:

<table>
      <thead>
        <tr></tr>
      </thead>
    <tbody ng-if="allData && allData.length > 0" ng-repeat="data in allData" >
          <tr >
              <td>
                  <div class="cursor-pointer" ng-click="data.rows = !data.rows">
                      <p>open</p>
                  </div>
              </td>
              <td>{{data.foodName}}</td>
              .....
          </tr>
            <tr ng-repeat="a in data.avaiable" ng-show="data.rows" ng-if="data.avaiable && data.avaiable.length > 0">
              ....
              <td>{{a.foodCount}}</td>
          </tr>
      </tbody>
      <tbody ng-if="!allData || allData.length == 0">
        <tr class="yourClass">
          <td colspan="3">
             <span translate="generic.NO_DATA_FOUND"></span> 
          </td>
        </tr>
      </tbody>
</table>
Shaishab Roy
  • 16,335
  • 7
  • 50
  • 68