I am using ng-table plugin to paginate a table like this:
$scope.ngtableParams = new ngTableParams({}, {
counts:false,
getData: function(params) {
return $http.get($rootScope.app.authApi + 'questions/' + selectedSubtopic.id).then(function(data) {
params.total(data.data.length);
return data.data;
});
}
});
Funnily ng-table calls getData() function everytime a user clicks on page numbers. And hits the entire thing again and fetches all the records and displays them. So pagination is essentially useless.
I need to have a client side pagination. Is it possible with ng-table?
Tried this as well
$http.get($rootScope.app.authApi + 'questions/' + selectedSubtopic.id)
.success(function(data){
$scope.ngtableParams = new ngTableParams({count:5}, {
counts:[],
paginationMaxBlocks: 13,
paginationMinBlocks: 2,
total:data.length,
getData: function(params) {
return data;
}
});
});
Same result with the above as well!
With the latest version of ng-table I end up using the following:
function IssueCtrl(NgTableParams, IssueService) {
var self = this;
loadTable();
function loadTable() {
IssueService.getIssues().then(function (issues) {
self.tableParams = new NgTableParams({
page: 1,
count: 5
}, {
dataset: issues // might be data instead of dataset depending on ng-table version
});
});
}
}
Client side pagination is properly working thanks to dataset.
So it should be something like this for OP:
$http.get($rootScope.app.authApi + 'questions/' + selectedSubtopic.id)
.success(function(result){
$scope.ngtableParams = new ngTableParams({count:5}, {
counts:[],
paginationMaxBlocks: 13,
paginationMinBlocks: 2,
total:result.length,
dataset: result // might be data instead of dataset depending on ng-table version
});
});
Related
My project outputs results to a DataTable from an AngularJS controller function, but I'm running into some strangeness when I try to modify my search params. The first rendering of the table works as expected. But when I select different options and run the search again, extra rows appear in the table, but the info section shows the previous search's row count, and changing the number of rows shown via the length menu causes the new rows to disappear. Here's my table declaration, using attributes to wire up DataTables:
<table ui-jq="dataTable" ui-options="dataTableOptions" id="search-results" class="display nowrap datatable cell-borders" style="width: 100%;">
And this is my AngularJS controller code:
$scope.dataTableOptions = {
dom: "lfBrtip",
lengthMenu: [[25, 50, -1], [25, 50, "All"]],
language: {
emptyTable: 'No items matched your search criteria'
},
buttons: [
{
text: 'Export',
className: 'button button:hover',
extend: 'csv'
}
]
};
$scope.getItemInfo = function (model) {
$http({
method: 'POST',
url: $scope.getUrl('/My/ServerSide/Url'),
data: { model: $scope.model }
}).then(function successCallBack(response) {
$scope.model.SearchResults = response.data;
}, function errorCallback(response) {
alert("There was an error gathering the entity information. Please try again");
});
};
I'm not sure why submitting new queries with different params doesn't simply update the data in the DataTables table. Any suggestions?
I ended up using a bit of an ugly hack to get this to work. Even DataTables author wasn't sure how to get around the issue of using AngularJS with DataTables, so I had to force a reinitialization every time the form posted. I persisted the search params to localStorage, and called location.reload(). Then when the page loads and the AngularJS init() function runs, I pick up the search params and call the search function from inside an Angular document ready function, like this:
$scope.init = function () {
$scope.ValidationErrors = [];
$scope.model = {};
$scope.model.SearchResults = [];
$scope.model.ItemNumber = localStorage.getItem("itemNumber");
$scope.model.StartDate = localStorage.getItem("startDate");
$scope.model.EndDate = localStorage.getItem("endDate");
angular.element(document).ready(function () {
if ($scope.model.ItemNumber) {
$scope.getItemRecords();
}
});
localStorage.clear();
};
And then of course I clear the localStorage after the query. Not terribly elegant, but it'll have to do for now.
I need to change the order of scope, save but me back an error that save() is not a function.
I'm using restangular to create the objects.
The function is triggered Onsort, I tried using http, but also gives me error.
$scope.onChange = function() {
ApiRestangular.all($scope.section).getList($scope.query).then(function(res){
$scope.items = res;
order = ApiRestangular.copy(res);
console.log(order);
$scope.sortOptions = {
animation : 150,
onSort: function(){
order.put().then(function(){
toast.msgToast($scope.section+ ' ...Ordem atualizada!');
});
}
};
});
};
I want to show table parameters (page, count, filter, etc.) in the url. so I use the following code in my controller :
$scope.tableParams = new ngTableParams(
angular.extend({
page : 1,
count: 10
},
$location.search()), {
getData: function ($defer, params) {
$location.search(params.url()); // put params in url
var query = getQuery();
query.limit = params.count();
query.offset = (params.page() - 1) * params.count();
getTotalCount().success(function () {
Content.prototype.find(query)
.success(function (response) {
$scope.tableParams.total($scope.totalCount);
var data = $filter('populateObjects')(response.data, query.fields);
$defer.resolve(data);
});
});
}
});
I do pagination and filtering on server side.
without applying filters on the table everything goes ok and the pagination works correctly. but every time I apply a filter on the table url change twice. the first time it is ok. something like this :
http://faraketabadmin/src/#/content/list?page=7&count=10&filter%5Bname%5D=g&filter%5Btype_id%5D=4
but after a moment it will again reset to page 1 like this :
http://faraketabadmin/src/#/content/list?page=1&count=10&filter%5Bname%5D=g&filter%5Btype_id%5D=4
I am trying to make ng-table work by example 6 (ajax data loading) but instead of using mock backend I use actual DreamFactory backend connected to MongoDB. My relevant code looks like this now:
MainApp.factory('Servant', function ($resource) {
"use strict";
console.log('loading');
return $resource('https://dsp-mydspname.cloud.dreamfactory.com:443/rest/mongodb/tablename/:id/?app_name=appname&fields=*', {}, { update: { method: 'PUT' }, query: {
method: 'GET',
isArray: false
} });
});
var MainCtrl = function ($scope, $timeout, $resource, Servant, ngTableParams) {
"use strict";
$scope.action="Add";
var Api = Servant;
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10, // count per page
}, {
total: 0, // length of data
getData: function($defer, params) {
// ajax request to api
Api.get(params.url(), function(data) {
$timeout(function() {
// update table params
params.total(data.record.length);
// set new data
$defer.resolve(data.record);
}, 500);
});
}
});
}
The table is displying data but it displays all data on one page, I cant figure out how to pass "count" and "offset" parameters into my api call. Any help would be appreciated.
Sorry for the delayed response. I played a little with ng-table and found that I was spending a lot of time trying to make it work and couldn't get it to. So..I thought it would be more helpful to show you how to build your own table with pagination so you can adapt it for any situation that may arise using DreamFactory. Here's the code. You should be able to copy and paste. Just make sure to add your table fields to the table row for data. The table headers will populate automatically.
Here is the controller and the service with comments:
.controller('TableCtrl', ['$scope', 'Servant', function($scope, Servant) {
// function to get records for building the table
var _getRecords = function(fieldsStr, limitInt, offsetInt, schemaBool) {
Servant.get({fields: fieldsStr, limit: limitInt, offset: offsetInt, include_schema: schemaBool},
function(data) {
$scope.table = data;
}
)
};
// Get the total records on load
Servant.get({fields: 'id'}, function(data) {
// Get the total number of records
$scope.totalRecords = data.record.length;
});
// Options for rest call
$scope.fields = '*';
$scope.currentOffset = 0;
$scope.limit = 4;
// Used to do pagination
// store total records
$scope.totalRecords = 0;
// store page objects
$scope.pageObjs = [];
// Get initial data
_getRecords($scope.fields, $scope.limit, $scope.currentOffset, true);
// Pagination
$scope.next = function() {
//check if we are on the last page
if ($scope.currentOffset == $scope.pageObjs[$scope.pageObjs.length - 1].pageOffset) {
return false;
}
// we are not
// advance the page
else {
$scope.currentOffset = $scope.currentOffset + $scope.limit;
_getRecords($scope.fields, $scope.limit, $scope.currentOffset, true);
}
};
// change page directly
$scope.changePage = function (offsetInt) {
$scope.currentOffset = offsetInt;
_getRecords($scope.fields, $scope.limit, $scope.currentOffset, true);
};
$scope.back = function() {
// are we on the first page
if ($scope.currentOffset == 0) {
return false
}
// we are not
// go previous page
else {
$scope.currentOffset = $scope.currentOffset - $scope.limit;
_getRecords($scope.fields, $scope.limit, $scope.currentOffset, true);
}
};
// watch for total records to be populated. When we have this number
// we can generate our page objects that will help build our pagination
$scope.$watch('totalRecords', function(newValue, oldValue) {
var numPages = Math.ceil(newValue / $scope.limit);
for(var i = 0; i < numPages; i++) {
$scope.pageObjs.push({pageNumber: i, pageOffset: i*$scope.limit})
}
});
}])
.service('Servant', ['$resource', function($resource) {
// define and return our $resource
// replace /rest/db/TheTable with your mongodb/tablename
// you don't need the port either
return $resource('http://localhost:8081/rest/db/TheTable',
{
// set params to bind too
app_name: APP_NAME
fields: '#fields',
limit: '#limit',
offset: '#offset'
},
{
// set update method to 'PUT'
update: {
method: 'PUT'
}
}
)
}]);
Here is the template i used:
<table class="table">
<!-- this will build the table headers dynamically -->
<!-- they will populate in order of the table's schema -->
<tr>
<th data-ng-repeat="field in table.meta.schema.field">
{{field.name}}
</th>
</tr>
<!-- replace these fields with your field names -->
<!-- for example: {{row.YOUR_FIELD_NAME}} -->
<tr data-ng-repeat="row in table.record">
<td>
{{row.id}}
</td>
<td>
{{row.first_name}}
</td>
<td>
{{row.last_name}}
</td>
</tr>
</table>
<!-- this will build dynamically as well-->
<ul class="pagination">
<li data-ng-click="back()"><a>«</a></li>
<li data-ng-click="changePage(page.pageOffset)" data-ng-repeat="page in pageObjs"><a>{{page.pageNumber + 1}}</a>
</li>
<li data-ng-click="next()"><a>»</a></li>
</ul>
I'm trying to implement server-side pagination on an AngujarJS app but haven't figured out how to get the grand total (not the per-request total) items in a given JSON response without having to do an additional request:
$scope.books = [];
$scope.limit = 3;
$scope.offset = 0;
$scope.search = function () {
Books.query({ q: $scope.query, limit: $scope.limit, offset: $scope.offset },
function (response) {
$scope.books = response;
}
);
};
$scope.previous = function () {
if ($scope.offset >= $scope.limit) {
$scope.offset = $scope.offset - $scope.limit;
$scope.search();
}
}
$scope.next = function () {
if ($scope.offset <= $scope.limit) {
$scope.offset = $scope.offset + $scope.limit;
$scope.search();
}
}
I've been looking at great contributed directives such as ng-table and ng-grid which already implement this as well as other useful features but I just want to be able to implement this one functionality from scratch to really learn the basics.
Sounds like you are struggling with your api more than angular.
See the answer below for suggestions for the api.
What’s the best RESTful method to return total number of items in an object?