AngularJS: $defer.resolve() not binding data to table - angularjs

Below is my HTML code for loading data in a table.
<table id="users" class="dashboard-widget msbf-table" ng-table="usersTableParams" hide-pagination="false" show-filter="true">
<tr ng-repeat = "user in users" ng-click="usersClicked($event, user.userId);">
<td data-title="'User login'" sortable="'userLogin'" filter="{'userId' : 'text'}">{{user.userId}}</td>
<td data-title="'User role'" sortable="" filter="{'roleName' : 'text'}">{{user.roleName}}</td>
</tr>
</table>
This is my code for populating data in the table:
$scope.usersTableParams = new ngTableParams({
page: startPage,
count: rowsPerPage,
sorting: {
userId: 'asc'
},
filter: {
userId: '',
roleName:''
}
},
{
total: $scope.users.length,
getData: function($defer, params){
// use build-in angular filter
var orderedData = getFilteredSortedData($scope.users, params);
//var orderedData = params.filter() ? $filter('filter')($scope.users, params.filter()) : $scope.users;
//$scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
params.total(orderedData.length); // set total for recalc pagination
$defer.resolve(getSlicedData(orderedData,params));
}
});
var getFilteredSortedData = function(data, params) {
if (params.filter()) {
data = $filter('filter')(data, params.filter());
}
if (params) {
data = params.sorting() ? $filter('orderBy')(data, params.orderBy()) : data;
}
console.log('Filtered Data: '+JSON.stringify(data));
console.log('Filtered Data size: '+data.length);
return data;
};
//slices the data for the current page, checked
var getSlicedData = function(data, params) {
var slicedData = data.slice((params.page() - 1) * params.count(), params.page() * params.count());
console.log('Sliced Data: '+JSON.stringify(slicedData));
console.log('Sliced Data size: '+data.length);
return slicedData;
};
The problem is that the data is coming correctly to the variable 'slicedData', however, this doesn't get's populated in the HTML table. What I suspect is that the line :
$defer.resolve(getSlicedData(orderedData,params))'
is not working. Any pointers / idea are welcome.
Thanks & Regards
Nishant Kumar

I finally figured out what was going wrong.
<table id="users" class="dashboard-widget msbf-table" ng-table="usersTableParams" hide-pagination="false" show-filter="true">
<tr ng-repeat = "user in users" ng-click="usersClicked($event, user.userId);">
....
</tr>
</table>
The
ng-repeat = "user in users"
should be replaced with
ng-repeat = "user in $data"
if you are using
getData in ngTableParams
to customize your data that is being displayed.
Based on my understanding, this happens because the getData() function puts data with all other details in $data rather than the variable that actually stores it. This $data variable is responsible for data that will be rendered based on configurations specified for the table when declaring the parameters for the table.
Hope you all concur with my understanding. Since I am new to Angular JS, so I might have provided explanation based on wrong assumptions so corrections of any sort are most welcome and thanks to all StackFlow followers and contributors for helping me out here.

You need to call $apply, or trigger a digest after the resolve is called.
Change getData to be:
getData: function($defer, $timeout, params){
// use build-in angular filter
var orderedData = getFilteredSortedData($scope.users, params);
//var orderedData = params.filter() ? $filter('filter')($scope.users, params.filter()) : $scope.users;
//$scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
params.total(orderedData.length); // set total for recalc pagination
$defer.resolve(getSlicedData(orderedData,params));
if (!$scope.$$phase) {
$scope.$digest();
}
}
You could also try wrapping $defer.resolve in a $timeout, this triggers a digest - Try this:
getData: function($defer, params){
// use build-in angular filter
var orderedData = getFilteredSortedData($scope.users, params);
//var orderedData = params.filter() ? $filter('filter')($scope.users, params.filter()) : $scope.users;
//$scope.users = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
params.total(orderedData.length); // set total for recalc pagination
$timeout(function() {
$defer.resolve(getSlicedData(orderedData,params));
})
}
The reason you need to do this is asnychronous code is not picked up by angularJS's watchers.

Related

angularjs - ngTable - issue with dynamic filter in controller

I want to create a filter for my ngTable.
In the controller at the root (not in a function) I do :
$scope.filters = {
nomSociete: 'test'
}
then
$scope.tableParamsContacts.reload();
$scope.tableParamsContacts = new ngTableParams({
page: 1, // show first page
count: 10,
filter : $scope.filters,
sorting: {
nom:'asc',
prenom:'asc'
}
}, {
total: dataContact.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var filteredData = params.filter() ?
$filter('filter')(dataContact, params.filter()) :
data;
var orderedData = params.sorting() ?
$filter('orderBy')(filteredData, params.orderBy()) :
dataContact;
params.total(orderedData.length); // set total for recalc pagination
if(params.total() < (params.page() -1) * params.count()){
params.page(1);
}
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
It works
But if I place
$scope.filters = {
nomSociete: 'test'
}
in a function in my controller:
vm.onClientSelect = function(affaire){
$scope.filters = {
nomSociete: 'test'
}
$scope.tableParamsContacts.reload();
}
It doesn't work, the value of the filter doesn't appear in the ng table, and the ng table gets empty.
I don't understand why.
Change the filter directly from within your ngTableParams like this:
$scope.filters = {
nomSociete: 'test'
}
$scope.tableParamsContacts.filter($scope.filters);
$scope.tableParamsContacts.reload();

AngularJS Firebase database ng-repeat filtered data into ngtable with ngTableParams

I filter one Firebase database based on another and concatenate the result into one $scope and ng-repeat the $scope array projectslist in a ngtable with ng-repeat="obj in projectslist", which works fine!
however, when I want to add ngTableParams to my table, it breaks and shows only the first object in the array. This time I ng-repeat like this: ng-repeat="obj in $data".
here is the console log of the concatenated array:
here is the controller:
app.controller('ProjectCtrl', ["$scope", "$filter", "ngTableParams", "firebase", "Auth", "DatabaseRef", "$firebaseArray", "$firebaseObject",
function ($scope, $filter, ngTableParams, firebase, Auth, DatabaseRef, $firebaseArray, $firebaseObject) {
var userId = firebase.auth().currentUser.uid;
$scope.projectslist = [];
var projectsRef = DatabaseRef.ref('/users/' + userId).orderByKey().once("value")
.then(function onSuccess(snapshot) {
snapshot.child("projects").forEach(function (childSnapshot) {
var userprojects = childSnapshot.val();
var projectquery = DatabaseRef.ref("projects").orderByKey().equalTo(userprojects);
var list = $firebaseArray(projectquery);
$scope.list = $firebaseArray(projectquery);
list.$loaded(function(){
$scope.projectslist = $scope.projectslist.concat(list);
});
var data = $scope.list;
data.$loaded().then(function(data) {
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 7, // count per page
}, {
dataset: data,
filterSwitch: true,
getData: function ($defer, params) {
var filteredData = params.filter() ? $filter('filter')(data, params.filter()) : data;
var orderedData = params.sorting() ? $filter('orderBy')(filteredData, params.orderBy()) : data;
params.total(data.length);
// set total for recalc pagination
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
});
});
}]);
The question is:
how to ng-repeat the data in a table with ngTableParams working as well, filtering, sorting, pagination?
You need to first sort your data, then go for filtering and then you can apply pagination on the data.
$scope.tableParams = new NgTableParams(
{
page : 1, // show first page
count : 5, // count per page
},
{
getData : function($defer, params) {
{
if (!$scope.projectslist|| !$scope.projectslist.length) { return; }
$scope.data = params.sorting() ? $filter('orderBy')($scope.projectslist, params.orderBy()) : $scope.projectslist;
$scope.data = params.filter() ? $filter('filter')($scope.data, params.filter()):$scope.data;
$scope.data = $scope.data.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.data);
}
}
});
Then you can use it in html like below defined
<table ng-table="tableParams" class="table table-striped responsive" show-filter="true" border="1" cellspacing="1" style="padding-left: 100px;padding-right: 100px;">
<tbody ng-repeat="obj in $data">
<tr ng-form="rowForm">
<td data-title="'Project Name'" filter="{'project_name':'text'}" sortable="'project_name'"
style="overflow: auto; -webkit-overflow: auto;"
><label>{{obj.project_name}}</label>
</td>
<!--<td>
More rows </td>-->
</table>

Iterate through all the records in all the pages in a Angular.js Datatable ng-table

I have a ng-table (angular.js datable) implementation with 25 records per page, on the page i have a submit button on clicking which i need to iterate through all records in all the pages to find which records have been modified in this table.
below is my code with which i can only iterate through the records in the current selected page, not the rest of the pages.
$scope.tableParams = new NgTableParams(
{
page: 1,
count: 25,
},
{
total: records.length,
getData: function ($defer, params) {
$scope.data = params.sorting() ? $filter('orderBy')(records, params.orderBy()) : result;
$scope.data = params.filter() ? $filter('filter')($scope.data, params.filter()) : $scope.data;
$scope.data = $scope.data.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.data);
}
});
var skus = [];
angular.forEach($scope.tableParams.data, function (product) {
if (product.quantity > 0) {
var sku =
{
AddToCart: true,
CategoryId: product.categoryId,
PriceCharged: product.displayPrice,
Quantity: product.quantity,
SkuCode: product.skuCode
}
skus.push(sku);
}
});
Probably you could use event ngTableEventsChannel.onDatasetChanged to catch modified row and copy it to a new object.
You might also try to use ng-change on edited cell.
And remember that you have all your records in records object.

ngTable.reload() unable to refresh ng-table does not show new data second time

ngTable.reload() unable to refresh ng-table does not show new data second time
code for index.js where i'm binding ng-table data.
First time databinding working properly. second time data is not binding properly. it shows previous data.
so basiccally it is unable to bind data and unable to refresh
$http.get("GetValidationsDataForTable", { params: { "entity": entity } })
.success(function (response) {
$scope.tableValue = response;
$scope.tableParams = [];
$scope.tableParams = new ngTableParams(
{
page: 1, // show first page
count: 5 // count per page
},
{
groupBy: 'Entity',
total: $scope.tableValue.length,
getData: function ($defer, params) {
var orderedData = params.filter() ?
$filter('filter')($scope.tableValue, params.filter()) :
$scope.tableValue;
var orderedData = params.sorting() ?
$filter('orderBy')($scope.tableValue, $scope.tableParams.orderBy()) : scope.tableValue;
orderedData = params.filter ?
$filter('filter')(orderedData, params.filter()) :
orderedData;
params.total(orderedData.length);
$defer.resolve($scope.tableValue.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
$scope.tableParams.reload();
})
code for index.cshtml
<table id="tblValue" ng-table="tableParams" class="customTable" style="table-layout:fixed;max-width:100%">
<tbody ng-repeat="group in $groups">
<tr ng-hide="group.$hideRows" ng-repeat="validation in group.data" style="table-layout:fixed;">
<td data-title="'Property'" style="width:10%;text-align:left !important;overflow:hidden;">
<label id="lblProperty" ng-model="validation.Property" for="Property" ng-hide="editmode" style="width:97%;word-wrap:break-word; overflow-wrap:break-word;">{{validation.Property}}</label>
<select class="form-control" data-ng-model="validation.PropertyChoice" data-ng-options="choice.Name for choice in CurrentEntityProperties" ng-change="ChangeValidationRules(validation)" ng-show="editmode" style="width:100%; ">
<option value="" style="margin-left:25px">-Select Property-</option>
</select>
</td>
</tr>
</tbody>
</table>
why ngtable.reload() does not work and also not showing new data second time?
Solution is :
$scope.tableParams = {};
$http.get("GetValidationsDataForTable", { params: { "entity": entity } })
.success(function (response) {
$scope.tableValue = response;
$scope.tableParams = [];
$scope.tableParams = new ngTableParams(
{
page: 1, // show first page
count: 5 // count per page
},
{
groupBy: 'Entity',
total: $scope.tableValue.length,
getData: function ($defer, params) {
var orderedData = params.filter() ?
$filter('filter')($scope.tableValue, params.filter()) :
$scope.tableValue;
var orderedData = params.sorting() ?
$filter('orderBy')($scope.tableValue, $scope.tableParams.orderBy()) : scope.tableValue;
orderedData = params.filter ?
$filter('filter')(orderedData, params.filter()) :
orderedData;
params.total(orderedData.length);
$defer.resolve($scope.tableValue.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
$scope.tableParams.reload();
})
i.e before every request make table parameters blank.
Solution for this problem is make table parameters blanks before any request to the data.
$scope.GetValidationsDataForTable = function(entity) {
// $("div").removeClass("container body-content");
$scope.tab1eParams = {};
SpinStart();
$http.get("GetValidationsDataForTable", {
params: {
"entity": entity
}
}).success(function(response) {
var resultArray = response;
SpinStop();
if (!$.isArray(resu1tArray) || !resultArray.1ength) {
$scope.HideFormVa1ue();
alert("Ho record found for this selection.");
}
else {
$scope.ShowFormVa1ue();
$scope.rows = response;
$scope.groupby = 'Entity',
$scope.tab1eParams = new ngTableParams({
page: 1,
count: 50,
filter: {},
sorting: {}
},
{
groupBy: $scope.groupby,
counts: [],
total: function() {
return $scope.rows.1ength;
},
getData: function($defer, params) {
$defer.resolve($scope.rows.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
You must clone params.filter() before using your service and use params.filter().yourFilter in HTML data binding.
Like that you do not need to use reload(), the ngTable will reload automatically.
Regards.

How to insert a row via ajax with NgTable?

Ok, i´m trying to do something very simple, here is my code:
<tr data-ng-repeat="data in $data | filter:searchText">
and i´ve this function, it´s called when i want to generate my table...
$scope.init = function (obj) {
if (isValid(obj)) {
generateService.sendUrlViaPost(obj.url, obj.params).then(function (response) {
$scope.$data = response;
$scope.tableParams = new ngTableParams({
page: obj.page,
count: obj.count,
}, {
total: $scope.grid.data.length,
getData: function ($defer, params) { //$data
orderedData = params.sorting() ? $filter('orderBy')($scope.$data, params.orderBy()) : $scope.$data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
Calling it at my html(it´s working fine)
data-ng-init="init({url: '/Professional/GetAll', params: false, page: 1, count: 10})"
The problem is when i call it when i submit my form and i want to reload via ajax and insert one row at my ngTable...
gridService.init({ url: '/Professional/GetAll', params: false, page: 1, count: 10});
Why my ngTable isn´t reloading? I think that the problem is with my ng-repeat because it isn´t reloading my table...

Resources