How to insert a row via ajax with NgTable? - angularjs

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...

Related

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.

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

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.

AngularJS reloading ngTable from ng-change event

I am populating ngTable using the following which works fine:
$scope.data = ClientService.query(
{
state: $scope.currentStateId,
parentId: $scope.parentId
});
$scope.data.$promise.then(function (data) {
$scope.tableParams = new ngTableParams(
{
page: 1, // show first page
count: $scope.pageCount, // count per page
sorting: { Name: 'asc' },
filter: { Name: ''}
},
{
total: data.length,
getData: function ($defer, params) {
var orderedData = params.filter() ? $filter('filter')(data, params.filter()) : data;
orderedData = params.sorting() ? $filter('orderBy')(orderedData, params.orderBy()) : orderedData;
params.total(orderedData.length); // set total for recalc pagination
$scope.accounts = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count());
$defer.resolve($scope.accounts);
}
});
});
I now wish to update the ngTable from an ng-change event which sets a new $scope.currentStateId as follows:
$scope.stateChange = function () {
//$state.go('root.account.clients.list', { state: $scope.currentStateId, parentId : $scope.parentId }, { reload : true })
//var sel = $scope.currentStateId;
$scope.data = ClientService.query(
{
state: $scope.currentStateId,
parentId: $scope.parentId
});
$scope.tableParams.reload();
};
The ClientService.query hits the server with the correct parameters and returns the correct data but the ngTable is not updated.
Can someone please help.
Update (correct answer)
Promises, by design, can be resolved only once. As a result, nesting new ngTableParams inside of $scope.data.$promise.then(function (data) { limits your ability to update the data at a later point.
Instead, put the callback inside of the getData function so that you can reset $scope.data with a new promise before calling $scope.tableParams.reload():
$scope.data = ClientService.query({
...
});
$scope.tableParams = new ngTableParams({
...
getData: function ($defer, params) {
$scope.data.$promise.then(function (data) {
var orderedData = params.filter() ? $filter('filter')(data, params.filter()) : data;
...
$defer.resolve($scope.accounts);
});
}
});
$scope.stateChange = function () {
$scope.data = ClientService.query({
...
});
$scope.tableParams.reload();
};
Previous Answer (incorrect)
You have a synchronous function call (your ngTable update) following an asynchronous call (the ClientService query). So, the table update executes before the data comes back.
Wrap the table update call in callback that fires once the promise is resolved:
$scope.data = ClientService.query(
{
state: $scope.currentStateId,
parentId: $scope.parentId
});
$scope.data.$promise.then(function (data) {
$scope.tableParams.reload();
};

Ng-table access to nested fields while grouping

I'm trying grouping by nested field, but groupBy doesn't work,it works only by primary fields.
$scope.groupby = ' ';
$scope.tableParams = new ngTableParams({
page: 1,
count: 10,
sorting: {
name: 'asc'
}
}, {
total: function () {
return $scope.alert.length;
},
groupBy: 'alertRuleCategory.name',
getData: function ($defer, params) {
var orderedData = params.sorting() ? $filter('orderBy')($scope.alert, $scope.tableParams.orderBy()) : $scope.alert;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
Sample of alert element
{
name: 'hello',
alertRuleCategory: {
id: 1;name: 'test'
},
id: 5
};
Can you help me, to find some workaround?
Use a function for groupBy. Passing your alert object into the groupBy function allows you to access its deep properties.
groupBy: function (alert) {
return alert.alertRuleCategory.name;
}
Plunker

Resources