Expand/collapse odd row in AngularJs - 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">

Related

AngularJs - allow only one item to be selected in Table

I am using smart table. I have a logic behind where I only need one item to be selected. My current table code allow multiple lines to be selected.
This is my HTML:
<table st-safe-src="flow3.dataSet" st-table="flow3.displayed" class="table table-striped">
<thead>
<tr>
<th st-sort="method">Method</th>
<th st-sort="sample">Sample</th>
<th st-sort="parameters">Parameters</th>
</tr>
</thead>
<tbody ui-sortable ng-model="flow3.displayed">
<tr ng-repeat="row in flow3.displayed track by $index" style="cursor: move;" ng-click="row.selected = !row.selected; flow3.selectRow($event, row)" ng-class="{success: row.selected}">
<td>{{row.method.name}}</td>
<td>{{row.sample}}</td>
<td>
<span ng-repeat="parameter in row.parameters">{{parameter.methodInputParameter.name}} : {{parameter.value}}<br/></span>
</td>
<td>
<button type="button" ng-click="flow3.removeItem(row)"
class="btn btn-danger btn-sm btn-round pull-right"
ng-disabled="flow3.confirmDisabled">
<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</tbody>
</table>
This is my JS:
flow3.selectRow = function($event, row) {
flow3.selectedItem = row;
}
If you want the only one row with selected property set to true, you should modify your selectRow method to accept the collection of all rows and then de-select all before selecting clicked one:
flow3.selectRow = function($event, row, rows) {
//de-select all
angular.forEach(rows, function(r){ r.selected = false; });
//select clicked
row.selected = true;
flow3.selectedItem = row;
}
ng-click="flow3.selectRow($event, row, flow3.dataSet)"
If you want to apply different css class to the clicked/selected item you probably can leave your selectRow method as is (since we have the selected item as flow3.selectedItem) and change the condition in the ngClass directive to be (if rows have some unique id property for example):
ng-class="{success: row.id === flow3.selectedItem.id}"
Hope this helps.
I'd recommend looking at the smart table github page and use guide here.
In particular the section relevant to your question is 'Select Data Rows'.
Essentially you need to use the st-select-row attribute along with the st-select-mode to configure click within your table row (tr) elements.

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>
...

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.

angularJS - Repeating tr's in a table, but dynamically adding more rows while looping

Since examples always tell more then just words here is what I would like to do in another language
<tr>
<c:forEach items="${items}" var="item">
<td>...</td>
<td>...</td>
<td>...</td>
<c:if test="${item.showWarning}">
</tr><tr><td colspan="3">${item.warning}</td>
</c:if>
</tr>
So this will loop over a set of items and show some properties of these items. If there is a warning, a new row will be added underneath the current row in which the warning will be shown. However, how can I do this in angularJs? If I put a ng-repeat on the tr, it will stop at the first end tag of tr. I have read on some other threads that this is not very easily done, but how can it be done? And yes, I really do want to use a table. Here is my contrived example with angularjs which is obviously not working as I would like it to. Any pointers how this can be done?
JSBin example with tr-ng-repeat
Currently (1.0.7/1.1.5) you can't output data outside the ng-repeat, but version 1.2(see youtube video AngularJS 1.2 and Beyond at 17:30) will bring the following syntax(adapted to your example):
<tr ng-repeat-start="item in items">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr ng-repeat-end ng-show="item.showWarning">
<td colspan="3">{{item.warning}}</td>
</tr>
The idea is that whatever is between -start and -end will be repeated including the -end element.
One solution that I can think of is having multiple tbody tags within the same table. Here is a discussion on the use of multiple tbody tags within the same table.
So, for your issue, you could have the following setup:
<table ng-controller="ItemController">
<thead>
<th>Name</th>
<th>Description</th>
<th>warning?</th>
</thead>
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3" style="text-align: center">Warning !!!</td>
</tr>
</tbody>
</table>
Repeat the table body as many times as there are entries for the table and within it have two rows - one to actually display the row entry and one to be displayed conditionally.
You can repeat over the tbody
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3">Warning !!!</td>
</tr>
</tbody>
Also you do not need to wrap the ng-show expression in {{}}, you can just use item.warning

Resources