Reputation: 2169
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?
Upvotes: 1
Views: 1188
Reputation: 16805
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>
Upvotes: 0
Reputation: 2043
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>
Upvotes: 3
Reputation: 7072
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.
Upvotes: 1
Reputation: 1607
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
Upvotes: 2