Working on an AngularJS project and I've ran into the following problem:
When using locally stored / hard coded data, the pagination works fine.
When using remotely stored data, the pagination does not work properly.
I have searched quite a bit, but couldn't find the solution to my problem, so here are the code snippits:
The HTML:
<div ng-controller="ngTableCtrl">
<p><strong>Pagina:</strong> {{tableParams.page()}}</p>
<p><strong>Aantal weergegeven:</strong> {{tableParams.count()}}</p>
<table ng-table="tableParams" class="table table-striped" template-pagination="custom/pager">
<tr ng-repeat="x in names">
<td data-title="'Name'">{{x.Name}}</td>
<td data-title="'City'">{{x.City}}</td>
<td data-title="'Country'">{{x.Country}}</td>
</tr>
</table>
<script type="text/ng-template" id="custom/pager">
<ul class="pager ng-cloak">
<li ng-repeat="page in pages"
ng-class="{'disabled': !page.active, 'previous': page.type == 'prev', 'next': page.type == 'next'}"
ng-show="page.type == 'prev' || page.type == 'next'" ng-switch="page.type">
<a ng-switch-when="prev" ng-click="params.page(page.number)" href="">« Previous</a>
<a ng-switch-when="next" ng-click="params.page(page.number)" href="">Next »</a>
</li>
<li>
<div class="btn-group">
<button type="button" ng-class="{'active':params.count() == 2}" ng-click="params.count(2)" class="btn btn-default">2</button>
<button type="button" ng-class="{'active':params.count() == 5}" ng-click="params.count(5)" class="btn btn-default">5</button>
<button type="button" ng-class="{'active':params.count() == 10}" ng-click="params.count(10)" class="btn btn-default">10</button>
<button type="button" ng-class="{'active':params.count() == 15}" ng-click="params.count(15)" class="btn btn-default">15</button>
</div>
</li>
</ul>
</script>
</div>
The JS:
app.controller('ngTableCtrl2', function ($scope, $http, $filter, ngTableParams) {
$http.get('http://www.w3schools.com/angular/customers.php')
.success(function (response) {$scope.names = response.records;});
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 5, // count per page
sorting: {
name: 'asc' // initial sorting
}
}, {
total: data.length, // length of data
getData: function ($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ? $filter('orderBy')(data, params.orderBy()) : data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
The webpage ( live version: http://178.62.232.175:8080/STANDARD/#/app/table/data ) shows all results in the first table (remote, from $http.get), whilst the second table, shows only the set results?! (2, 5, 10, 15)
The code is identical, except for:
<tr ng-repeat="x in names">
used to display remote data and is replaced by:
<tr ng-repeat="x in $data">
to display raw data as such:
var data = [{
Name: "Alfreds Futterkiste", City: "Berlin", Country: "Germany"},{
Name: "Ana Trujillo Emparedados", City: "México D.F.", Country: "Mexico"},{
Name: "Antonio Moreno Taquería", City: "México D.F.", Country: "Mexico"},{
Name: "Around the Horn", City: "London", Country: "UK"},{
Name: "B's Beverages", City: "London", Country: "UK"},{
Name: "Berglunds snabbköp", City: "Luleå", Country: "Sweden"},{
Name: "Blauer See Delikatessen", City: "Mannheim", Country: "Germany"},{
Name: "Blondel père et fils", City: "Strasbourg", Country: "France"},{
Name: "Bólido Comidas preparadas", City: "Madrid", Country: "Spain"},{
Name: "Bon app", City: "Marseille", Country: "France"},{
Name: "Bottom-Dollar Marketse", City: "Tsawassen", Country: "Canada"},{
Name: "Cactus Comidas para llevar", City: "Buenos Aires", Country: "Argentina"}
];
The pagination of the second table works as it should. What must I edit to make it work with remote data?
First of all your code is using the local data array as a source in ngTables getData callback and it is not clear what you are presenting as a comparison since you did not actually try AJAX Data Loading from the official examples .
Instead I would expect it to have an api call to the server using $http.get.
Remember for server side paging to work you must update the total count each time you query for data because they may have changed. Also you will have to consider a server side solution for sorting as well.
Here is a working sample using the github api as a test service.
var app = angular.module('main', ['ngTable']);
app.controller('MainCtrl', function($scope, $http, ngTableParams) {
$scope.tableParams = new ngTableParams({
page: 1,
count: 5,
}, {
getData: function ($defer, params) {
var page = params.page();
var size = params.count();
var testUrl = 'https://api.github.com/search/repositories';
var search = {
q: 'angular',
page: page,
per_page: size
}
$http.get(testUrl, { params: search, headers: { 'Content-Type': 'application/json'} })
.then(function(res) {
params.total(res.data.total_count);
$defer.resolve(res.data.items);
}, function(reason) {
$defer.reject();
}
);
},
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.3.3/ng-table.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.3.3/ng-table.min.js"></script>
<div ng-app="main" ng-controller="MainCtrl">
<table ng-table="tableParams" class="table table-striped table-bordered table-hover table-condensed">
<tr ng-repeat="repo in $data">
<td data-title="'id'">{{repo.id}}</td>
<td data-title="'name'">{{repo.name}}</td>
<td data-title="'owner'">{{repo.owner.login}}</td>
</tr>
</table>
<div>
Related
Using AngularJS 1.3.4.
I have a html table that is being populated from an web api where I make an http request to get that data and populate my html table. My example json is as below:
{
id: 1,
firstName: "John",
lastName: "Rein",
status: 'available'
},
{
id: 2,
firstName: "David",
lastName: "Gumry",
status: 'not available'
}
Now I have a dropdown below the table, and I am using ui-select for it. I want to populate this dropdown based on the status in my json. For example in my json above I have 2 status available and not available. I want my dropdown to have these values. After I populate my dropdown, I want to filter my table based on the dropdown value that is selected. I have my dropdown as:
<ui-select tagging ng-model="selected" theme="bootstrap">
<ui-select-match placeholder="Pick one...">{{$select.selected.value}}</ui-select-match>
<ui-select-choices repeat="val in values | filter: $select.search track by val.value">
<div ng-bind="val.value | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
I have created my jsfiddle at:
https://jsfiddle.net/aman1981/wfL1374x/
I am not sure how can I bind the results from json to my DDL and filter my table.
You had a few issues that needed handling including redundant use of ng-app and ng-controller. Also, it seems as though ui-select works best using the ControllerAs syntax which is a preferred approach in general.
After these changes and others (too many to list), here's the working code:
angular.module('myApp', ['ui.select'])
.controller("PeopleCtrl", function($http) {
var vm = this;
vm.people = [];
vm.isLoaded = false;
vm.values = [];
vm.loadPeople = function() {
// *** I had to comment this out as it is not allowed in the SO Code Snippet but is fine for your code
//$http({
// method: 'POST',
// url: '/echo/json/',
// data: mockDataForThisTest
//}).then(function(response, status) {
// console.log(response.data);
// vm.people = response.data;
//});
vm.people = [{
id: 1,
firstName: "John",
lastName: "Rein",
status: 'available'
},
{
id: 2,
firstName: "David",
lastName: "Gumry",
status: 'not available'
}
];
vm.values = [...new Set(vm.people.map(obj => ({
value: obj.status
})))];
};
vm.selected = {
key: null,
value: null
};
var mockDataForThisTest = "json=" + encodeURI(JSON.stringify([{
id: 1,
firstName: "John",
lastName: "Rein",
status: 'available'
},
{
id: 2,
firstName: "David",
lastName: "Gumry",
status: 'not available'
}
]));
})
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.20.0/select.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-sanitize/1.2.23/angular-sanitize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.20.0/select.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body ng-app="myApp">
<div ng-controller="PeopleCtrl as ctrl">
<br>
<p> Click <a ng-click="ctrl.loadPeople()">here</a> to load data.</p>
<h2>Data</h2>
<div class="row-fluid">
<table class="table table-hover table-striped table-condensed">
<thead>
<tr>
<th>Id</th>
<th>First Name</th>
<th>Last Name</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="person in ctrl.people | filter: {status: ctrl.selected.value} : true">
<td>{{person.id}}</td>
<td>{{person.firstName}}</td>
<td>{{person.lastName}}</td>
<td>{{person.status}}</td>
</tr>
</tbody>
</table>
</div>
<br><br>
<div width="50px">
<ui-select tagging ng-model="ctrl.selected" theme="bootstrap">
<ui-select-match placeholder="Pick one...">{{$select.selected.value}}</ui-select-match>
<ui-select-choices repeat="val in ctrl.values | filter: $select.search track by val.value">
<div ng-bind="val.value | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>
</div>
</body>
I am using filesaver.js to export my div (with multiple tables) to excel. I am able to export it as XLS using the code below.
var blob = new Blob([document.getElementById('exportable').innerHTML], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
});
saveAs(blob, "Test Report using FileSaver.xls");
However, I want to export my div to XLSX. Can anyone help? I have tried changing the MIME type to XLSX, but didn't help.
Update
W3C does not implemented .xlsx so the browsers too. But you can use alsql a js library which export data as a valid .xlsx here is the jsfiddle or run below code
function myCtrl($scope) {
$scope.exportData = function () {
alasql('SELECT * INTO XLSX("Report.xlsx",{headers:true}) FROM ?',[$scope.items]);
};
$scope.items = [{
name: "John Smith",
email: "j.smith#example.com",
dob: "1985-10-10"
}, {
name: "Jane Smith",
email: "jane.smith#example.com",
dob: "1988-12-22"
}, {
name: "Jan Smith",
email: "jan.smith#example.com",
dob: "2010-01-02"
}, {
name: "Jake Smith",
email: "jake.smith#exmaple.com",
dob: "2009-03-21"
}, {
name: "Josh Smith",
email: "josh#example.com",
dob: "2011-12-12"
}, {
name: "Jessie Smith",
email: "jess#example.com",
dob: "2004-10-12"
}];
};
<script src="https://cdn.jsdelivr.net/alasql/0.3.6/alasql.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.7.2/xlsx.core.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="myCtrl">
<button ng-click="exportData()">Export</button>
<br />
<div id="exportable">
<table width="100%">
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>DoB</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in items">
<td>{{item.name}}</td>
<td>{{item.email}}</td>
<td>{{item.dob | date:'MM/dd/yy'}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
I need to use angular in order to get data from a web endpoint to fill this table. I have a list created with random names, but I need it to filled with data from a link instead. I still need to create the social media links as well.
Either way, can someone show me how to do it keeping in mind that I don't know much about angular at all. thank you.
html:
<!DOCTYPE html>
<html>
<head>
<title>Angular JS </title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
<script type="text/javascript" src="folder/main.js"></script>
<script src="http://code.angularjs.org/1.4.8/angular.js"></script>
<script src="http://code.angularjs.org/1.4.8/angular-resource.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.js"></script>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body ng-app="MyForm">
<div ng-controller="myCtrl">
<h3>List students</h3>
<div class="container-fluid">
<pre>Click header link to sort, input into filter text to filter</pre>
<hr />
<table class="table table-striped">
<thead>
<tr>
<th>Edit</th>
<th>
ID
</th>
<th> Name </th>
<th>Social Media </th>
</tr>
</thead>
<tbody>
<tr>
<td>Filter =>></td>
<td> <input type="text" ng-model="search.name" /></td>
<td> <input type="text" ng-model="search.age" /> </td>
<td><input type="text" ng-model="search.gender" /> </td>
</tr>
<tr ng-repeat="user in students | orderBy:predicate:reverse | filter:paginate| filter:search" ng-class-odd="'odd'">
<td>
<button class="btn">
Edit
</button>
</td>
<td>{{ user.name}}</td>
<td>{{ user.age}}</td>
<td>{{ user.gender}}</td>
</tr>
</tbody>
</table>
<pagination total-items="totalItems" ng-model="currentPage"
max-size="5" boundary-links="true"
items-per-page="numPerPage" class="pagination-sm">
</pagination>
</div>
</div>
</body>
</html>
js:
<script>
var app = angular.module('MyForm', ['ui.bootstrap', 'ngResource']);
app.controller('myCtrl', function ($scope) {
$scope.predicate = 'name';
$scope.reverse = true;
$scope.currentPage = 1;
$scope.order = function (predicate) {
$scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
$scope.predicate = predicate;
};
$scope.students = [
{ name: 'Kevin', age: 25, gender: 'boy' },
{ name: 'John', age: 30, gender: 'girl' },
{ name: 'Laura', age: 28, gender: 'girl' },
{ name: 'Joy', age: 15, gender: 'girl' },
{ name: 'Mary', age: 28, gender: 'girl' },
{ name: 'Peter', age: 95, gender: 'boy' },
{ name: 'Bob', age: 50, gender: 'boy' },
{ name: 'Erika', age: 27, gender: 'girl' },
{ name: 'Patrick', age: 40, gender: 'boy' },
{ name: 'Tery', age: 60, gender: 'girl' }
];
$scope.totalItems = $scope.students.length;
$scope.numPerPage = 5;
$scope.paginate = function (value) {
var begin, end, index;
begin = ($scope.currentPage - 1) * $scope.numPerPage;
end = begin + $scope.numPerPage;
index = $scope.students.indexOf(value);
return (begin <= index && index < end);
};
});
</script>
the data looks like this:
{"id":"11","name":"A Cooperativa","full_address":"Rua Bar\u00e3o de Viamonte 5, 2400-262 Leiria","location":"Leiria","council":"Leiria","country":"Portugal","lat":"39.7523042","lng":"-8.7825576","type":"various","facebook":"https:\/\/www.facebook.com\/pages\/A-Cooperativa-MerceariaTasca\/1559630810945570","facebook_id":"","gmaps":"https:\/\/www.google.pt\/maps\/place\/R.+Bar%C3%A3o+de+Viamonte+5,+2410+Leiria\/#39.7523042,-8.7825576,17z\/data=!3m1!4b1!4m2!3m1!1s0xd2273a29462db11:0x49a3f9a45cd9eb80","tripadvisor":"http:\/\/www.tripadvisor.com\/Restaurant_Review-g230085-d8154189-Reviews-A_Cooperativa-Leiria_Leiria_District_Central_Portugal.html","zomato":"","website":"","email":"cooperativa.tasca#hotmail.com","telephone":"912635324","active":"1","updated":"2015-08-17 09:01:05"}
I'm not sure if I did get this right, but:
You want to get the students from a web endpoint as json?
Then you would write something like this in angular:
app.controller('myCtrl', function ($scope, $http) {
...
$scope.students = [];
$scope.totalItems = 0;
$http.get('https://www.domain.com/api/resource')
.then(function success(response) {
$scope.students = response.data;
$scope.totalItems = $scope.students.length;
}, function failed(reason) {console.log(reason);})
...
});
But you should use separated files, services etc.
<table class="table table-bordered">
<tr ng-repeat="x in AppliedJob">
<td>{{x.JobName}}</td>
<td> <span class="dropdown" ng-repeat="y in AppliedCenter| unique: 'Location' " ng-if="y.JobName==x.JobName">
{{$index+1}}){{y.Location}}
</span> </td></tr> </table>
Output of above code
1) Tester : 1)India 2)USA 3)Australia
2) Developer : 4)Japan 5)China
Required Output
1) Tester : 1)India 2)USA 3)Australia
2) Developer : 1)Japan 2)China
I want to set $Index to 1.
It happens because you're filtering using ng-if which is not affect array and it's indexes, it just removes the element from DOM. You should use filter instead of y.JobName==x.JobName comparison in ng-if so yours ng-repeat expression should be like this y in AppliedCenter | unique: 'Location' | filter: { JobName: x.JobName }. See example:
angular
.module('Test', [])
.controller('TestController', ['$scope', function($scope) {
$scope.cities = ["New York", "LA"];
$scope.jobs = [{ name: "QA", city: "New York"}, { name: "Frontend", city: "New York"}, {name: "Backend", city: "New York"}, {name: "DBA", city: "LA"}, { name: "QA", city: "LA"}];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app="Test">
<div ng-controller="TestController">
<table>
<tr ng-repeat="city in cities">
<td ng-bind="city"></td>
<td>
<span ng-repeat="job in jobs | filter:{city: city}">{{($index + 1) + ")" + job.name}} </span>
</td>
</tr>
</table>
</div>
</div>
I want to take the value of the filter input, is that possible? I have this table
with that code
<td data-title="'Transaccion'" filter="{id_transaccion: 'text'}" sortable="'id_transaccion'">
<span editable-text="pago.id_transaccion" e-name="id_transaccion" e-form="rowform" e-required="">{{pago.id_transaccion}}</span>
</td>
I have the filter attr, and I tested everything trying to get the value of the field transacction of the filter, but nothing works, anyone knows how to get it?
You can access the filters object with the method filter() of the instance of NgTableParams. If you get your table data with 'getData' instead of 'dataset' (as in the example below), everytime you change a filter value the function 'getData' will be executed and you can access your updated filter object there and make any data manipulation you want. Look at the code of the snippet below:
(function() {
"use strict";
var app = angular.module("myApp", ["ngTable"]);
app.controller("demoController", demoController);
demoController.$inject = ["NgTableParams", "$filter"];
function demoController(NgTableParams, $filter) {
var self = this;
var simpleList = [{
name: 'ww',
age: 234,
money: 45,
country: 'pan'
}, {
name: 'xx',
age: 24,
money: 55,
country: 'col'
}, {
name: 'yy',
age: 454,
money: 82,
country: 'cr'
}, {
name: 'zz',
age: 345,
money: 34,
country: 'mex'
}];
self.tableParams = new NgTableParams({
// initial filter
filter: {
name: "w"
}
}, {
getData: getData
});
function getData(params) {
/*****************************
* LOOK HERE!!!!!
******************************/
// The filter object
var filterObj = params.filter();
self.ngTableFilters = filterObj;
// Filtering the list using the filter object...
var filteredList = $filter('filter')(simpleList, filterObj);
return filteredList;
}
}
})();
(function() {
"use strict";
angular.module("myApp").run(setRunPhaseDefaults);
setRunPhaseDefaults.$inject = ["ngTableDefaults"];
function setRunPhaseDefaults(ngTableDefaults) {
ngTableDefaults.params.count = 5;
ngTableDefaults.settings.counts = [];
}
})();
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.js"></script>
<div ng-app="myApp" class="container-fluid">
<div class="row" ng-controller="demoController as demo">
<div class="col-xs-12">
<h3>ngTable directive</h3>
<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'}">{{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>
</div>
<div class="col-xs-12">
<h3>Filters:</h3>
<pre>{{ demo.ngTableFilters | json }}</pre>
</div>
</div>
</div>