how to create a collapsing row for smarttable? - angularjs

I am trying to implement a collapsing row in my smarttable. This is a row that is only visible once the user wants to show some more detail. This is what it looks like now:
<table st-table="displayed" class="table table-striped">
<thead>
<tr>
<th st-ratio="20" st-sort="firstName">first name</th>
<th st-ratio="20" st-sort="lastName">last name</th>
<th st-ratio="10" st-sort="age">age</th>
<th st-ratio="30" st-sort="email">email</th>
<th st-ratio="20" st-sort="balance">balance</th>
</tr>
</thead>
<tbody>
<input type="checkbox" ng-model="show"/> {{show}}
<tr ng-repeat="row in displayed">
<td st-ratio="20">{{row.firstName}}</td>
<td st-ratio="20">{{row.lastName | uppercase}}</td>
<td st-ratio="10">{{row.age}}</td>
<td st-ratio="30">{{row.email}}</td>
<td st-ratio="20">{{row.balance | currency}}</td>
</tr>
<tr ng-show="show">
<td>hallo</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-center">
<div st-items-by-page="20" st-pagination=""></div>
</td>
</tr>
</tfoot>
</table>
Is there a way of displaying a collapsing detailrow for this table?
plunkr ref:http://plnkr.co/edit/8lSx2v?p=preview

<table st-table="displayed" class="table table-striped">
<thead>
<tr>
<th st-ratio="20">#</th>
<th st-ratio="20" st-sort="firstName">first name</th>
<th st-ratio="20" st-sort="lastName">last name</th>
<th st-ratio="10" st-sort="age">age</th>
<th st-ratio="30" st-sort="email">email</th>
</tr>
</thead>
<tbody>
<tr ng-repeat-start="row in displayed">
<td>
<button ng-if="row.expanded" ng-click="row.expanded = false" class="btn btn-xs btn-default glyphicon glyphicon-chevron-down"></button>
<button ng-if="!row.expanded" ng-click="row.expanded = true" class="btn btn-xs btn-default glyphicon glyphicon-chevron-right"></button>
</td>
<td st-ratio="20">{{row.firstName}}</td>
<td st-ratio="20">{{row.lastName | uppercase}}</td>
<td st-ratio="10">{{row.age}}</td>
<td st-ratio="30">{{row.email}}</td>
</tr>
<tr ng-if="row.expanded" ng-repeat-end="">
<td colspan="2">
<b>Balance<br /></b>
</td>
<td colspan="3" st-ratio="20">{{row.balance | currency}}</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="5" class="text-left">
<div st-items-by-page="5" st-pagination=""></div>
</td>
</tr>
</tfoot>
</table>

you can call a function with ng-change, and in there you expand the displayd array.
like I did in the plunker:
var limitVers = [];
for (var j = 0; j < 50; j++) {
limitVers.push(createRandomItem());
}
var addedItems = [];
for (var k = 0; k < 20; k++) {
addedItems.push(createRandomItem());
}
var expaVers = limitVers.concat(addedItems);
$scope.displayed = limitVers;
$scope.update = function(show){
show ? $scope.displayed = expaVers : $scope.displays = limitVers;
}

Related

Is it possible to add each value of ngFor as one value?

There are some values returned by ngFor in Total Column. Now I wanted to add those value to get a one grandTotal. I didn't get the idea. Anyone can help me??
In below second table:
I want {{sales.Total}} values to be added and return grand total.
/*****First Table*****/
<table class="table">
<thead>
<tr>
<th scope="col">S.N</th>
<th scope="col">Items</th>
<th scope="col">Quantity</th>
<th scope="col">Rate</th>
<th scope="col">Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let sales of salesTransaction, let i = index">
<th>{{i+1}}</th>
<!-- <td mat-cell *matCellDef="let salesTransaction">{{salesTransaction.ProductName}}</td> -->
<td>{{sales.ProductName}}</td>
<td>{{sales.Quantity}}</td>
<td>{{sales.Rate}}</td>
<td>{{sales.Total}}</td>
</tr>
</tbody>
</table>
/*****Second Table*****/
<table class="right-table">
<tbody>
<tr>
<th>Sub-Total</th>
<td *ngFor="let sales of salesTransaction">{{sales.Total}}</td>
</tr>
<hr class="divider">
<tr>
<th>Tax</th>
<td>Happy</td>
</tr>
<hr class="divider">
<tr>
<th>Grand Total</th>
<td>0000</td>
</tr>
</tbody>
</table>
You need to create a method that returns grand total
getGrandTotal(): number {
return this.salesTransaction.reduce((acc, val) => acc += val.Total, 0);
}
<tr>
<th>Grand Total</th>
<td>{{getGrandTotal()}}</td>
</tr>
<table class="right-table">
<tbody>
<tr>
<th>Sub-Total</th>
<td *ngFor="let sales of salesTransaction">{{sales.Total}}</td>
</tr>
<hr class="divider">
<tr>
<th>Tax</th>
<td>Happy</td>
</tr>
<hr class="divider">
<tr>
<th>Grand Total</th>
<td>{{salesTransaction.reduce((total, value) => total += value.Total, 0)}}</td>
</tr>
</tbody>
</table>

How to use ui-grid with ng-repeat and angular-ui.bootstrap.collapse

I have a table where I use ng-repeat and angular-ui collapse to show data on it. I would like to implement ui-grid, but I'm not even near a solution.
Here's a Plunker of my code: https://plnkr.co/edit/mKeRaDv22WzBXjRT67oO?p=preview
The html code:
<div ng-controller="MyCtrl">
<table class="table table-striped">
<thead>
<tr>
<th style="width: 20%">A: </th>
<th style="width: 20%">B: </th>
<th style="width: 15%">C: </th>
<th style="width: 15%">D: </th>
<th style="width: 15%">E: </th>
<th style="width: 15%">F: </th>
</tr>
</thead>
<tbody ng-repeat="data in myData" ng-click="element.isCollapsed = !element.isCollapsed">
<tr>
<td>{{data.a}}</td>
<td>{{data.b}}</td>
<td>{{data.c}}</td>
<td>{{data.d}}</td>
<td>{{data.e}}</td>
<td>{{data.f}}</td>
<td></td>
</tr>
<tr collapse="element.isCollapsed" ng-show="element.isCollapsed">
<td colspan="2">{{data.g}} </td>
<td colspan="2">{{data.h}} </td>
<td colspan="2">{{data.i}} </td>
</tr>
<tr collapse="element.isCollapsed" ng-show="element.isCollapsed">
<td colspan="2">{{data.j}} </td>
<td colspan="2">{{data.k}} </td>
<td colspan="2">{{data.l}} </td>
</tr>
<tr collapse="element.isCollapsed" ng-show="element.isCollapsed">
<td colspan="6">{{data.m}} </td>
</tr>
</tbody>
</table>
</div>

How to clone and print data in angular

I have a table which prints data from a JSON. Every row have an delete option.
I want to print the deleted data into a new table. I have managed to print data in console but unable to add it into view.
Below is the code:
Controller
$scope.deletedItems = [];
var counter = 0
$scope.removeRow = function (idx) {
console.log(idx);
$scope.TTNdata.splice(idx, 1);
var deletedArray = $scope.TTNdata.slice(idx, 1);
//console.log(deletedArray);
$scope.deletedItems.push(deletedArray);
console.log($scope.deletedItems);
counter++;
$('#counter').html(counter);
};
View:
<table id="deleted-rows" class="">
<thead>
<th>Sr. No</th>
<th>ID</th>
<th>First Name</th>
<th>Second Name</th>
<th>Gender</th>
<th>Email</th>
<th>Image</th>
<th>Remove</th>
</thead>
<tbody>
<tr ng-repeat="item in deletedItems | orderBy:'id'">
<td>{{$index+1}}</td>
<td>{{item.id}} </td>
<td>{{item.first_name}}</td>
<td>{{item.last_name}}</td>
<td>{{item.gender}}</td>
<td>{{item.email}}</td>
<td><img src="{{item.photo}}" alt="{{item.first_name}} {{item.last_name}} photo"></td>
<td class=""> <span style="cursor:pointer" ng-click="removeRow($index)" title="Remove Record" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
<table class="table bordered">
<thead>
<tr>
<th>Sr. No</th>
<th>ID</th>
<th>First Name</th>
<th>Second Name</th>
<th>Gender</th>
<th>Email</th>
<th>Image</th>
<th>Remove</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="data in TTNdata | filter:bindtext | orderBy:'id'">
<td>{{$index+1}}</td>
<td>{{data.id}} </td>
<td>{{data.first_name}}</td>
<td>{{data.last_name}}</td>
<td>{{data.gender}}</td>
<td>{{data.email}}</td>
<td><img src="{{data.photo}}" alt="{{data.first_name}} {{data.last_name}} photo"></td>
<td class=""> <span style="cursor:pointer" ng-click="removeRow($index)" title="Remove Record" class="glyphicon glyphicon-remove"></span></td>
</tr>
</tbody>
</table>
Data is printing in console but not in table, every time i click remove it will generate a blank row in deleted table
What I am doing wrong?
Code on github https://github.com/sahilpopli/learningAngular.git
slice returns array, so try $scope.deletedItems.push(deletedArray[0]);
Or try to concatenate the arrays by doing so: $scope.deletedItems = $scope.deletedItems.concat(deletedArray);
A possible thing that you may need to think is that if you going to have paged tables, removing the object from a list with that index could not be a good thing.
My solution to your problem would be this(using the id instead of index). This is just scratch demonstrating a possible way to achieve what is your desire.
Code
angular.module('App', [])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.List = [{
Id: 1,
Name: 'Name1'
}, {
Id: 2,
Name: 'Name2'
}, {
Id: 3,
Name: 'Name3'
}];
$scope.newList = [];
var remove = function(itemId) {
var indexS = $scope.List.filter(function(item, index) {
return item.Id == itemId;
});
if (indexS.length == 1)
$scope.newList.push($scope.List.splice($scope.List.indexOf(indexS[0]), 1)[0])
};
$scope.removeMe = remove;
}]);
Markup
<body ng-app="App" ng-controller="MyCtrl">
<table>
<thead>
<th> Id </th>
<th> Name </th>
</thead>
<tbody>
<tr ng-repeat="item in List">
<td >{{item.Id}}</td>
<td >{{item.Name}}</td>
<td ng-click="removeMe(item.Id)">removeme</td>
</tr>
</tbody>
</table>
<table>
<thead>
<th> Id </th>
<th> Name </th>
</thead>
<tbody>
<tr ng-repeat="item in newList">
<td >{{item.Id}}</td>
<td >{{item.Name}}</td>
</tr>
</tbody>
</table>
Plunker

Multiple Filtered Counts with Angular

I have a list of users for each of my stores [model.stores.users] in JSON object and currently show the number of users against each store by accessing store.users.length
Now I want two extra counts, these counts are just based on the number of users with a simple boolean filter.
Count of Active Users is where user.is_user_active = true
Count of Pending Users is where user.is_user_active = false
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th class="hidden">ID</th>
<th>Name</th>
<th>Users</th>
</tr>
</thead>
<tbody class="tbl-jobs-data" ng-repeat="item in model.stores">
<tr data-toggle="collapse" class="accordion-toggle" data-target="#store_user{{$index}}">
<td class="hidden">{{item.id}}</td>
<td class="">{{item.name}}</td>
<td class="user-count">{{item.users.length}}</td>
</tr>
<tr ng-if="item.users.length > 0">
<td colspan="100" class="hiddenRow">
<div class="accordian-body collapse" id="store_user{{$index}}">
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>State</th>
<th>Is Active</th>
<th>Last Login</th>
</tr>
</thead>
<tbody class="tbl-search-data">
<tr ng-repeat="app in item.users">
<td>{{app.id}}</td>
<td>{{app.name}}</td>
<td>{{app.state}}</td>
<td>{{app.is_user_active}}</td>
<td>{{app.last_login}}</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
</div>
Just use filter, eg
<td class="active_user_count">
{{ (item.users | filter : { is_user_active: true }).length }}
</td>
<td class="pending_user_count">
{{ (item.users | filter : { is_user_active: false }).length }}
</td>
I hope I've got the syntax right, the Angular docs are down at the moment >:(

Nested Rows (Rowspan?) Within ng-repeat?

The following image is produced by the following code:
<div class="row" ng-show="result">
<div class="col-sm-12">
<table class="table">
<thead>
<tr>
<th>Group</th>
<th>Status</th>
<th>Result</th>
<th>Computations</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="r in result | orderBy:'-WarnResult.Value' | filter: { Status: 'warning'}">
<td>
{
<span ng-repeat="(k, v) in r.WarnResult.Group">
{{k}}={{v}}<span ng-hide="$last">,</span>
</span>
}
</td>
<td ng-bind="r.Status"></td>
<td>
<pre ng-bind="json(r.WarnResult.Value)"></pre>
</td>
<td>
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="c in r.WarnResult.Computations">
<td ng-bind="c.Text"></td>
<td ng-bind="c.Value"></td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr ng-repeat="r in result | orderBy:'-CritResult.Value' | filter: { Status: 'normal'}">
<td>
{
<span ng-repeat="(k, v) in r.CritResult.Group">
{{k}}={{v}}<span ng-hide="$last">,</span>
</span>
}
</td>
<td ng-bind="r.Status"></td>
<td>
<pre ng-bind="json(r.CritResult.Value)"></pre>
<pre ng-bind="json(r.WarnResult.Value)"></pre>
</td>
<td>
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="c in r.CritResult.Computations">
<td ng-bind="c.Text"></td>
<td ng-bind="c.Value"></td>
</tr>
</tbody>
</table>
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="c in r.WarnResult.Computations">
<td ng-bind="c.Text"></td>
<td ng-bind="c.Value"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</div>
</div>
I'd like to make it so the the results (The thing in the Pre boxes) lines up with their corresponding computations (The idea is both the WarnResult and CritResult are show when Status is 'normal'). It looks like maybe I want to use rowspan, or maybe something with ng-repeat-start and ng-repeat-stop, but I'm having trouble seeing the solution.
Decided to move the repeat to the tbody, which allows me to have two rows per iteration.
<table class="table">
<thead>
<tr>
<th>Group</th>
<th>Status</th>
<th>Expression</th>
<th>Result</th>
<th>Computations</th>
</tr>
</thead>
<tbody ng-repeat="r in result | orderBy:'-status_number'">
<tr>
<td rowspan="2">
{
<span ng-repeat="(k, v) in r.CritResult.Group">
{{k}}={{v}}<span ng-hide="$last">,</span>
</span>
}
</td>
<td rowspan="2" ng-bind="r.Status"></td>
<td>critical</td>
<td>
<pre ng-bind="json(r.CritResult.Value)"></pre>
</td>
<td>
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="c in r.CritResult.Computations">
<td ng-bind="c.Text"></td>
<td ng-bind="c.Value"></td>
</tr>
</tbody>
</table>
</td>
</tr>
<td>warning</td>
<td>
<pre ng-bind="json(r.WarnResult.Value)"></pre>
</td>
<td>
<table class="table table-striped table-condensed">
<tbody>
<tr ng-repeat="c in r.WarnResult.Computations">
<td ng-bind="c.Text"></td>
<td ng-bind="c.Value"></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>

Resources