ng-click is not working in table header - angularjs

Hi I am new to AngularJS. I am creating a sample application to sort the data in a table by clicking the table header. On the first click it should arrange it in ascending order. Second click it should arrange it to descending.
Below provided are the cshtml code.
<div ng-controller="myController">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th ng-click="sortData('firstname')">First Name</th>
<th>Last Name</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employee in employees|orderBy:'sortColumn'">
<td>{{employee.firstname | lowercase}}</td>
<td>{{employee.lastname| uppercase}}</td>
<td>{{employee.salary |currency:"$":1}}</td>
</tr>
</tbody>
</table>
</div>
Below provided are script for module
var myApp = angula
.module("myModule", [])
.controller("myController", function ($scope) {
var employee = [
{ firstname: "First", lastname: "Trueman", salary: "20001" },
{ firstname: "Second", lastname: "someone", salary: "20002" },
{ firstname: "Third", lastname: "apple", salary: "20003" },
{ firstname: "Fourth", lastname: "parrot", salary: "20004" },
{ firstname: "Fifth", lastname: "mat", salary: "20005" },
];
$scope.employees = employee;
$scope.sortColumn = "firstname";
$scope.reverseSort = false;
$scope.sortData = function (column) {
$scope.reverseSort = ($scope.sortColumn == column) ? !$scope.reverseSort : false;
$scope.sortColumn = column;
}
});
For some reason ng-click is not working. Does anyone face the same issue before., If yes can you help me with this.

There were two things needed to be fixed:
sortColumn should be used without the single quote as it is a variable
add reverseSort variable to the orderBy.
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th ng-click="sortData('firstname')">First Name</th>
<th>Last Name</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="employee in employees|orderBy: sortColumn : reverseSort">
<td>{{employee.firstname | lowercase}}</td>
<td>{{employee.lastname| uppercase}}</td>
<td>{{employee.salary |currency:"$":1}}</td>
</tr>
</tbody>
I've created a working plnkr here.

Related

Angular 1.x - How to display table with dynamic rows and columns

Aim - Display a dynamic table for both rows and columns as below -
Dynamic Header - The fund codes are values for "name" from the json object array.
Dynamic rows with values for Application, Redemption and Net
JSON object :
[
{
name: 'VBIF',
application: 1000,
redemption: -200,
netAppRed: 800
},
{
name: 'VCIF',
application: 1500,
redemption: -200,
netAppRed: 800
},
{
name: 'VMPF',
application: 2000,
redemption: 0,
netAppRed: 2000
},
{
name: 'VBIF-A',
application: 800,
redemption: 100,
netAppRed: 700
},
{
name: 'VMPF-A',
application: 43540,
redemption: 12550,
netAppRed: 30990
}
]
HTML :
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Fund Code</th>
<th>Application</th>
<th>Redemption</th>
<th>Net Application Redemption</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="cashflow in cashflows">
<td>{{cashflow.name}}</td>
<td>{{cashflow.application | currency}}</td>
<td>{{cashflow.redemption | currency}}</td>
<td>{{cashflow.netAppRed | currency}}</td>
</tr>
</tbody>
</table>
</div>
Current view displays :
Another option without need to change model:
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>Fund Code</th>
<th data-ng-repeat="cashflow in cashflows">{{cashflow.name}} </th>
</tr>
</thead>
<tbody>
<tr >
<td>Application</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.application | currency}}</td>
</tr>
<tr >
<td>Redemption</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.redemption | currency}}</td>
</tr>
<tr >
<td>NetAppRed</td>
<td data-ng-repeat="cashflow in cashflows">{{cashflow.netAppRed | currency}}</td>
</tr>
</tbody>
</table>
</div>
Resovled it by changing the model in the controller as below -
$scope.getHeaders = function (){
var keys = [];
angular.forEach(object, function (val, key) {
if(key !== '$$hashKey') { keys.push(key); }
});
return keys;
};
$scope.getValue = function () {
var values = [];
angular.forEach(object, function (val, key) {
if(key !== '$$hashKey') { values.push(val); }
});
return values;
};
The HTML updated as below -
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th></th>
<th ng-repeat="(header, value) in cashflows">
{{value.name}}
</th>
</tr>
</thead>
<tbody>
<tr>
<td>Application</td>
<td ng-repeat="row in cashflows">
{{row.application}}
</td>
</tr>
<tr>
<td>Redemption</td>
<td ng-repeat="row in cashflows">
{{row.redemption}}
</td>
</tr>
<tr>
<td>Net App & Red</td>
<td ng-repeat="row in cashflows">
{{row.netAppRed}}
</td>
</tr>
</tbody>
</table>
</div>
Final Output :
you can use ng-tables to show your dynamic data
here is example
[https://www.tutlane.com/tutorial/angularjs/angularjs-tables-with-ng-table][1]
if any query ask me on comment

How to use Nested ng-repeat to repeat table columns dynamically?

I want to make dynamic columns of a table and create a new object to save it in mongoDb.
I have first Array of Student as:
students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
and have second Array of Subjects as:
subjects = [{sName: "maths"},{sName: "science"}]
Here is the HTML
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>
Here is the Controller
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
The Output Looks like this.
The marks columns are repeating similar values. But i want one single finalObject to save my data.
Here is the jsFiddle of my problem https://jsfiddle.net/g8tn71tr/
The row subjects refer to the same NgModel row.marks which makes them have the same value.
You can solve it by making the ng-model refer to each of the subjects ng-model="row.marks[subject.sName]". This will result in that row.marks will become an object where each subject will be a key and the model will be in its value
(function(){
var app = angular.module('t', []);
app.controller('test',
[
'$scope',
function($scope)
{
$scope.students = [{id: "1", name: "abc"},{id: "2", name: "def"},{id: "3", name: "hij"}]
$scope.subjects = [{sName: "maths"},{sName: "science"}]
$scope.finalData = new Array();
$scope.finalData.push({
icon : false
});
$scope.action=function(index){
console.clear();
console.log($scope.finalData[index]);
if(index == $scope.finalData.length-1){
$scope.finalData[index].icon = true;
$scope.finalData.push({
icon : false
});
}else{
$scope.finalData.splice(index, 1);
}
};
}
]);
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app='t' ng-controller='test'>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th ng-repeat="subject in subjects">{{subject.sName}}</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in finalData track by $index">
<th><input type="text" ng-model="row.rollNo"/></th>
<th><input type="text" ng-model="row.fullName"></th>
<th ng-repeat="subject in subjects"><input type="text" ng-model="row.marks[subject.sName]"></th>
<th>
<button ng-click="action($index)">
add/remove
</button></th>
</tr>
</tbody>
</table>
</div>

ngtable custom filter of $index instead of filtering from dataset

<table ng-table="demo.tableParams" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td data-title="'Name'" filter="{name: 'text'}">{{$index}}</td>
<td data-title="'Age'" filter="{age: 'number'}">{{row.age}}</td>
<td data-title="'Money'">{{row.money}}</td>
<td data-title="'Country'" filter="{ country: 'select'}" filter-data="demo.countries">{{row.country}}</td>
</tr>
</table>
</div>
I have {{$index}} to print out the index number. I understand that i can filter easily using filter={age: 'number'} however i cannot do the same for $index as it is not part of the dataset from the JS.
I want to be able to filter $index via a input box instead of automatically filtering upon loading the page.
I don't think you can filter on $index. But you can simply extend you dataset before rendering the table.
Controller
$scope.data = [{
name: 'greg',
age:29,
money: 100.10
}, {
name: 'bob',
age:30,
money: 250.00
}];
for(var i = 0; i < $scope.data.length; i++) {
$scope.data[i].index = i;
}
$scope.table = new NgTableParams({ }, {
dataset: $scope.data
});
View:
<table ng-table="table" class="table table-condensed table-bordered table-striped">
<tr ng-repeat="row in $data">
<td data-title="'Index'" filter="{index: 'number'}">{{row.index}}</td>
<td data-title="'Name'" filter="{name: 'text'}">{{row.name}}</td>
<td data-title="'Age'" filter="{age: 'number'}">{{row.age}}</td>
<td data-title="'Money'" filter="{money: 'number'}">{{row.money}}</td>
</tr> </table>

disable or indicate the default sorting in angular smart-table

angular 1 there are 3 sort options: asc, default and desc
how can I change the sort so the sort will be only between desc and asc
and will show the default also only on the loading as happened in every table; the situation now is that there is situation with no sort at all in the third click;
thx
example :
<form>
<label for="predicate">selected predicate:</label>
<select class="form-control" id="predicate" ng-model="selectedPredicate" ng-options="predicate for predicate in predicates"></select>
</form>
<table st-table="rowCollection" class="table table-striped">
<thead>
<tr>
<th st-sort="firstName">first name</th>
<th st-sort="lastName">last name</th>
<th st-sort="birthDate">birth date</th>
<th st-sort="balance">balance</th>
<th>email</th>
</tr>
<tr>
<th>
<input st-search="firstName" placeholder="search for firstname" class="input-sm form-control" type="search"/>
</th>
<th colspan="3">
<input st-search placeholder="global search" class="input-sm form-control" type="search"/>
</th>
<th>
<input st-search="{{selectedPredicate}}" placeholder="bound predicate" class="input-sm form-control" type="search"/>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rowCollection">
<td>{{row.firstName | uppercase}}</td>
<td>{{row.lastName}}</td>
<td>{{row.birthDate | date}}</td>
<td>{{row.balance | currency}}</td>
<td><a ng-href="mailto:{{row.email}}">email</a></td>
</tr>
</tbody>
</table>
js:
app.controller('filterCtrl', ['$scope', '$filter', function (scope, filter) {
scope.rowCollection = [
{firstName: 'Laurent', lastName: 'Renard', birthDate: new Date('1987-05-21'), balance: 102, email: 'whatever#gmail.com'},
{firstName: 'Blandine', lastName: 'Faivre', birthDate: new Date('1987-04-25'), balance: -2323.22, email: 'oufblandou#gmail.com'},
{firstName: 'Francoise', lastName: 'Frere', birthDate: new Date('1955-08-27'), balance: 42343, email: 'raymondef#gmail.com'}
];
scope.predicates = ['firstName', 'lastName', 'birthDate', 'balance', 'email'];
scope.selectedPredicate = scope.predicates[0];
}]);
Found the solution:
adding st-skip-natural="true" for each field
<th class="tableColumn" st-skip-natural="true" st-sort>date</th>

how to create a nested grid in ngtable?

I am trying to create a nested grid in my ngtable like this:
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in $data">
<td data-title="'Name'">{{user.name}}</td>
<td data-title="'Age'">{{user.age}}</td>
<td data-title="'kids'">
<table ng-table="nestedtableParams" class="table">
<tr ng-repeat="nesteduser in $nesteddata">
<td data-title="'Name'">{{nesteduser.name}}</td>
<td data-title="'Age'">{{nesteduser.age}}</td>
</tr>
</table>
</td>
</tr>
</table>
question is: why is the nested data not displaying? here is a plunkr:
http://plnkr.co/edit/dKTtU89f7z6nQptgEZxN?p=preview
Got this working by adding the data to the $scope: (partial example code)
$scope.nesteddata = [{
name: "Kid Moroni",
age: 50
}, {
name: "Kid Tiancum",
age: 43
}, {
name: "Kid Jacob",
age: 27
}, {
name: "Kid Nephi",
age: 29
}, {
name: "Kid Enos",
age: 34
}];
And then, in the controller functions, refer to these $scope variables:
$scope.nestedtableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
total: $scope.nesteddata.length, // length of data
getData: function($defer, params) {
$defer.resolve($scope.nesteddata.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
Finally in the markup I left out the $ prefix, since this data is now in the scope:
<table ng-table="tableParams" class="table">
<tr ng-repeat="user in data">
<td data-title="'Name'">{{user.name}}</td>
<td data-title="'Age'">{{user.age}}</td>
<td>
<table ng-table="nestedtableParams" class="table">
<tr ng-repeat="user in nesteddata">
<td data-title="'Name'">{{user.name}}</td>
<td data-title="'Age'">{{user.age}}</td>
</tr>
</table>
</td>
</tr>
</table>
Working Plunker (Although I doubt that it makes sense to nest grids like this)

Resources