AngularJS : Use of ng-if and ng-class combination - angularjs

I have a table like this :
<tr>
<th scope="row">QUANTITÉ PRODUITE</th>
<td>{{hoursValues[0][0][0]}}</td>
<td>{{hoursValues[0][0][1]}}</td>
<td>{{hoursValues[0][0][2]}}</td>
<td>{{hoursValues[0][0][3]}}</td>
<td>{{hoursValues[0][0][4]}}</td>
<td>{{hoursValues[0][0][5]}}</td>
<td>{{hoursValues[0][0][6]}}</td>
<td>{{hoursValues[0][0][7]}}</td>
</tr>
<tr>
<th scope="row">OBJECTIF QUANTITÉ</th>
<td>{{hoursValues[0][2][0]}}</td>
<td>{{hoursValues[0][2][1]}}</td>
<td>{{hoursValues[0][2][2]}}</td>
<td>{{hoursValues[0][2][3]}}</td>
<td>{{hoursValues[0][2][4]}}</td>
<td>{{hoursValues[0][2][5]}}</td>
<td>{{hoursValues[0][2][6]}}</td>
<td>{{hoursValues[0][2][7]}}</td>
</tr>
I want to compare each column of a row with the other corresponding column, for example : hoursValues[0][0][0] && hoursValues[0][2][0] and according to this comparison, I want to apply the classes.
I mean, if hoursValues[0][0][0] > hoursValues[0][2][0], I want to display the result in green else red.
Can anyone help me ? What should I write in my controller ?

in each td just do this
<td ng-class="{true:'green', false:'red'}[hoursValues[0][0][0] > hoursValues[0][2][0]]">
obvius just change each column with corresponding one.
next td
<td ng-class="{true:'green', false:'red'}[hoursValues[0][0][1] > hoursValues[0][2][1]]">

Related

change class name on click and remove class on other click - Angular 4

Can some one help me to resolve this. I have table with different columns (TD). I want to select one cell and change its classname. when i click on other cell, i want to restore the classname in previously cell and change the classname on newly selected cell..
Please note: each cell have different classname. So i have to keep track of pervious class and selected element.
This is Angular 4 application.
my table:
<table class="table package-table stats">
<tbody>
<tr *ngIf="deptStatsModel.length>0">
<th (click)="setStatsActByDept($event,dt2,null)" class="st-th">ORG</th>
<th (click)="setStatsActByDept($event,dt2,'OD')" class="OverDue">Over Due</th>
<th (click)="setStatsActByDept($event,dt2,'NA')" class="NeedAttention">Need Att</th>
<th (click)="setStatsActByDept($event,dt2,'IA')" class="InProgress">In Prog</th>
<th (click)="setStatsActByDept($event,dt2,'CP')" class="Comp">Complete</th>
</tr>
<tr *ngFor="let model of deptStatsModel">
<td (click)="setActivitiesData($event,model, 'all','DPT')">{{model.deptName}}</td>
<td (click)="setActivitiesData($event,model, 'OD','DPT')">{{model.overDue}}</td>
<td (click)="setActivitiesData($event,model, 'NA','DPT')">{{model.needAtt}}</td>
<td (click)="setActivitiesData($event,model, 'IP','DPT')">{{model.inProg}}</td>
<td (click)="setActivitiesData($event,model, 'CP','DPT')">{{model.complete}}</td>
</tr>
<tr *ngIf="deptStatsModel.length==0">
<td style="text-align: left" colspan="5">No records found</td>
</tr>
</tbody>
</table>
I have on click as below:
setStatsActByDept(event,dt,type)
{
var target = event.target || event.srcElement ||
event.currentTarget;
this.prevDeptCss=target.cloneNode();
target.className="selected";
.........
}
I dont know what to do next..help please.
You're thinking about it in the wrong way. The code shouldn't modify the DOM. It should modify the state of the component. The template is the one responsible to apply CSS classes to DOM elements based on the state of the component.
Assuming, as your code seems to imply, that you want to select the header cells. Your code should simply look like the following.
In your component:
public selectedHeader: string;
In your view:
<th (click)="selectedHeader = 'ORG'" [ngClass]="selectedHeader === 'ORG' ? 'selected' : 'st-th'">ORG</th>
<th (click)="selectedHeader = 'OverDue'" [ngClass]="selectedHeader === 'OverDue' ? 'selected' : 'OverDue'">Over Due</th>
...

Expand/collapse odd row in AngularJs

I want to expand/collapse a row, I want to hide all odd rows and on clicking '+' button those hidden row should get visible, my current code is allowing me hide all the odd rows but on clicking '+' button all row are getting visible, my use case is to show only the odd row which is next to clicked even row.
<table class="table table-bordered">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Type</th>
</tr>
</thead>
<tbody ng-repeat="test in ctrl.SearchResults">
<tr ng-if="$even">
<td>
<button ng-click="ctrl.expanded = !ctrl.expanded" expand>
<span ng-bind="ctrl.expanded ? '-' : '+'"></span>
</button></td>
<td>{{test.apName}}</td>
<td>{{test.type}}</td>
</tr>
<tr ng-show="ctrl.expanded" ng-if="$odd">
<td></td>
<td>{{test.apName}}</td>
<td>{{test.type}}</td>
</tr>
</tbody>
</table>
The reason all the rows expand when you hit the plus, is that the variable expanded is on the controller. So all the rows are 'listening' to the same variable.
As atfornes pointed out in his answer, you could use the $index to identify each row. Another solution is to keep track of the current index on the controller and check for per row if he must be showed:
<tr ng-show="ctrl.expanded == $index" ng-if="$odd">
And on the click event of the plus sign you could have
ctrl.expanded = $index
Or you could handle this in the controller. In this case you can create a method on the controller which accepts the index and then set this index value to the controller's variable expanded.
At the button ng-click code, you could store the current $index with a code like:
<button ng-click="ctrl.expanded = !ctrl.expanded; ctrl.index = $index" expand>
then, you can change the ng-show condition to only display the item if ctrl.expanded and $index === ctrl.index + 1:
<tr ng-show="ctrl.expanded && $index === ctrl.index +1" ng-if="$odd">

Angularjs filter out

I have "item.adjustment". The value of adjustment either can be a positive number or a negative number. Based on the sign of the value, I have to display 'adjustments' in two different columns: Positive, and Negative columns.
below is a sample code for my scenario. Can any one help?
<tr>
<td>Positive</td>
<td>Negative</td>
</tr>
<tr>
<td>{{item.adjustment}}</td>
<td>{{item.adjustment}}</td>
</tr>
Can I do something like this?
<td ng-if="item.adjustment >= 0"/>
<td ng-if="item.adjustment < 0"/>
or any better ways?
ng-if will show/hide the element based on the condition if that is what you want. But if you want to show different style based on positive or negative value then its better to use ng-class.
E.g
<td ng-class="{ positive: item.adjustment >= 0 }/>
<td ng-class="{ negative: item.adjustment < 0 }/>
Then define these classes
.positive {
color: green;
}
.negative {
color: red;
}
You have to display them in seperate columns, but still render both <td>s. What you can do is wrap them in a span, because setting the ng-if on the <td> itself won't render the <td>, which causes the negative adjustments to be also in the first column.
<tr>
<td>Positive</td>
<td>Negative</td>
</tr>
<tr>
<td><span ng-if="item.adjustment >= 0">{{item.adjustment}}</span></td>
<td><span ng-if="item.adjustment < 0">{{item.adjustment}}</span></td>
</tr>
If I understand correctly what you want to do :
your JS
$scope.items = [{adjustment:1},
{adjustment:0.3},
{adjustment:-7},
{adjustment:0},
{adjustment:13},
{adjustment:-4},
{adjustment:-0.5}];
your HTML
<tr>
<td>Positive</td>
<td>Negative</td>
</tr>
<tr ng-repeat="item in items">
<td>{{item.adjustment >= 0 ? item.adjustment : ''}}</td>
<td>{{item.adjustment < 0 ? item.adjustment : ''}}</td>
</tr>
Assuming, you want to show/hide the text inside td element conditionally, you should add a span inside the td and use ng-if on that. With your approach, only one of the tds will be displayed for any given item in a table row.
<td><span ng-if="item.adjustment >= 0">item.adjustment</span></td>
<td><span ng-if="item.adjustment < 0">item.adjustment</span></td>
See the plunker here which highlights the problem with your approach

Angularjs - add additional row inside a tr ng-repeat

Ng-repeat is present on a table row
My query is how can we achieve the following:
<tr ng-repeat="x in y">
Looping here....
</tr>
Now as data object is looping on a <tr>. I have a scenario where I have to display data of 1 row in two <tr>.
Eg.
Table
Data1 data1.2 data1.3 data1.4
Data2 data2.2
Data2b data2.3 data2.4
Data3 data3.2 data3.3 data3.4
Data4 data4.2 data4.3
I.e. display data of 1 row in two
Can't use ng-repeat-end
1) You can combine ng-if with ng-repeat and 2) ng-repeat supports multi-element with ng-repeat-start and ng-repeat-end:
<tr ng-repeat-start="item in [1, 2, 3, 4, 5, 6]">
<td>{{item}}</td><td>something else</td>
</tr>
<tr ng-if="item % 2 === 0" ng-repeat-end>
<td colspan="2">-even</td>
</tr>
Demo
I modified the solution New Dev provided for my purposes & thought I'd share since it really saved me.
I needed a solution to repeat my table header row after every nth row as an alternative to a "frozen/fixed upon scrolling" header row, which just isn't feasible for my use case.
In this example, I'm showing the header row after every 25 rows, but not if it's going to be the last row in the table: (($index+1) != itemCollection.length).
<table class="table table-bordered">
<thead>
<tr>
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="item in itemCollection">
<td>{{item}}</td>
<td>{{$index}}</td>
</tr>
<tr ng-repeat-end="" ng-if="(($index+1) % 25 === 0) && ($index+1) != itemCollection.length">
<th>Column Header 1 - Value</th>
<th>Column Header 2 - Index</th>
</tr>
</tbody>
</table>
Check out the modified demo. For simplicity's sake, I used an inline collection, so the "not if it's going to be the last row in the table" logic isn't included (as you'll see with the unneeded column header at the very bottom), but you get the picture.
You need to repeat tbody instead of tr.
<tbody ng-repeat="x in y" >
<tr>
<td>{{X. row data}}</td>
<td>{{X. row data 2}}</td>
</tr>
<tr>
<td colspan="2">
{{X. secondRowData}}
</td>
</tr>
</tbody>
<tr ng-repeat-start=x in y>
<td>selectbox here
<tr\>
<tr ng-repeat-end ng-if=somecondition>
<td>label data <\td>
<\tr>
So now we have already used ng-repeat-end. Inside ng-repeat-end i have to display 2 rows for a single iteration.
<tr><td indexis1>selectbox<\td><\tr>
<tr><td indexis2>label primary<\td><\tr>
<tr><td indexis2>label secondary<\td><\tr>
This is a rough code snippet and there are numerous td already present in code.

ngRepeat with Table: Change a cell's display text

I have a list of mails which I want to show in a grid (<table>). Some of these mails have attachments. For their corresponding rows, I would like to show an attachment icon in the attachment column. For rest, it should be empty.
JsFiddle: http://jsfiddle.net/6s4Z5/
My template is as follows:
<table id="resultTable">
<thead>
<tr>
<th ng-repeat="columnId in schema.columnOrder">
<img src="icon_attach.png" ng-if="columnId == 'hasAttachments'">
{{schema.columns[columnId].displayText}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in results.mails">
<td ng-repeat="columnId in schema.columnOrder">
<img src="icon_attach.png" ng-if="columnId == 'hasAttachments' && row.hasAttachments">
<span ng-if="columnId != 'hasAttachments'" >{{ row[columnId] }}</span>
</td>
</tr>
</tbody>
</table>
where schema.columnOrder is an array of columnIds to be shown in the table.
This template is working but is this the best way to implement this? Moreover, I have to add an extra <span> for ng-if statement. Can that also be removed?
You pretty much can change it to something like:
<span ng-if='your check'><img src=''/>{{row[columnId}}</span>
You could set (in the controller) the value of the column hasAttachments to be the image you want to display there.

Resources