With Angular, I'm doing http request to take data. I've added ngTable and using it to display data. They correctly display in the table but I can't filters, sorting and delete them. Why?
js:
$scope.cancel = cancel;
function cancel(row, rowForm) {
var originalRow = resetRow(row, rowForm);
angular.extend(row, originalRow);
}
$scope.tableParams.reload().then(function(data) {
if (data.length === 0 && $scope.tableParams.total() > 0) {
$scope.tableParams.page($scope.tableParams.page() - 1);
$scope.tableParams.reload();
}
});
$http.get('my_url')
.success(function(data, status) {
$scope.data = data;
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
total: $scope.data.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')($scope.data, params.orderBy()) :
$scope.data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
html:
<table ng-table="tableParams" show-filter="true" class="table table-bordered table-striped">
<tr ng-repeat="row in data track by row.id">
<td title="'Id'" filter="{id: 'text'}" sortable="'id'">{{row.id}}</td>
<td title="'Company'" filter="{company: 'text'}" sortable="'company'">{{row.company}}</td>
<td title="'Email'" filter="{email: 'text'}" sortable="'email'">{{row.email}}</td>
<td title="'Note'" filter="{note: 'text'}" sortable="'note'">{{row.note}}</td>
<td>
<button class="btn btn-default btn-sm" ng-click="cancel(row, rowForm)"><span class="glyphicon glyphicon-remove"></span></button>
</td>
</tr>
</table>
You are not applying any filters inside getData method.
First, you need to filter the data, then you sort:
getData: function($defer, params) {
// I will use a copy of the data to always start with the original data
// array ($scope.data). If you are getting the data with $resource or $http
// you can replace the $scope.data with the data obtained (eg.: response.data)
var theData = angular.copy($scope.data);
// First we filter using the filter object provided by the
// method 'filter()' of ngTableParams instance.
var filterObj = params.filter(),
filteredData = $filter('filter')($scope.data, filterObj);
// Then we sort the FILTERED DATA ARRAY
// NOTICE that the first parameter provided to $filter('orderBy')
// is the filtered array <filteredData> and not the original
// data array.
var sortObj = params.sorting(),
orderedData = $filter('orderBy')(filteredData, sortObj);
// Then we return the final data array (orderedData)
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
Related
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>
I am new to angularjs
When I use search functionality works on first page only not on all the pages
search box
<input type="text" class="form-control" data-ng-model="campId.campaign_id" placeholder="Search here...">
In my html
<table ng-table="tableParams" class="table table-striped">
<tr ng-repeat="campaign in $data| filter: campId">
// my data hare
// if I added filter inside table then only its works here it will work for name
<td data-title="'Name'" sortable="'name'" filter = "{ 'name':'text' }"> <div contenteditable="true">
{{campaign.name}}</div>
</td>
</tr>
</table>
Below is js code for pagination
campaign.controller('campaignController', ['$scope', '$filter', 'ngTableParams', '$http', function($scope, $filter, ngTableParams, $http) {
$http.get("api/test")
.success(function(response) {
$scope.feilds = response.campaigns;
var length_of_dict = Object.keys($scope.feilds).length;
var keys_list = Object.keys($scope.feilds);
var data = $scope.feilds;
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 2 , // count per page
filter : {
campaign_id : '' // initial sorting
}
}, {
total: length_of_dict, // length of data
getData: function($defer, params) {
// use build-in angular filter
//alert(params) ;
var orderedData = params.filter() ?
$filter('filter')(data, params.filter()) : //This will be used to filter the dictionary array and return back only those resource objects that has the desired key the user is looking for.
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
}]);
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.
I am trying to get the code correct, I used ngTable a long time ago and I forgot how I got it to work. The Json is returning fine. But Nothing is going through ngTable.
var data = CustomerGet.query().then(function (data) {
$scope.customerArray = data;
}, function (reason) {
errorMngrSvc.handleError(reason);
});
//Customer Employee Table
$scope.tableParams = new ngTableParams({
count: data.length // hides pager
}, {
counts: [], // hides page sizes
groupBy: 'role',
total: data.length,
getData: function ($defer, params) {
var orderedData = params.sorting() ?
$filter('orderBy')(data, $scope.tableParams.orderBy()) :
data;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
View
<table ng-table="tableParams" class="table">
<tbody ng-repeat="group in $groups">
<tr class="ng-table-group">
<td colspan="{{$columns.length}}">
<a href="" ng-click="group.$hideRows = !group.$hideRows">
<span class="glyphicon" ng-class="{ 'glyphicon-chevron-right': group.$hideRows, 'glyphicon-chevron-down': !group.$hideRows }"></span>
<strong>{{ group.value }}</strong>
</a>
</td>
</tr>
<tr ng-hide="group.$hideRows" ng-repeat="user in group.data">
<td sortable="name" data-title="'Name'">
{{user.CustomerEmployees.CustomerEmployeeFirstName}}
</tr>
</tbody>
</table>
UPDATE
CustomerEmployeeGet.query()
.success(function (data, status) {
$scope.customerArray = data;
$scope.tableParams = new ngTableParams({
count: customerArray.length // hides pager
}, {
counts: [], // hides page sizes
groupBy: 'Role',
total: customerArray.length,
getData: function ($defer, params) {
var orderedData = params.sorting() ?
$filter('orderBy')(customerArray, $scope.tableParams.orderBy()) :
customerArray;;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
I am making some progress.
Error
TypeError: undefined is not a function
and that is at the .success line
I skipped my http factory and did everything from the controller
//Get CustomerEmployees
$http.get('/api/apiCustomerEmployee')
.success(function (data, status) {
$scope.tableParams = new ngTableParams({
count: data.length // hides pager
}, {
counts: [], // hides page sizes
groupBy: 'Role',
total: data.length,
getData: function ($defer, params) {
var orderedData = params.sorting() ?
$filter('orderBy')(data, $scope.tableParams.orderBy()) :
data;;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
});
I have a grid developed using ng-table and I need to remove selected item from grid table after removing from server-side. Already tried to call the grid loading ajax again, but it's not working.
My Controller,
app.controller('blockController', function($scope, $filter, $q, ngTableParams, $sce, Block) {
// Fetch data from server using RESTful API
$scope.load = function() {
// load serverside data using http resource service
Block.get({}, function (response) { // success
$scope.results = response.data;
var data = response.data; // store result to variable
// Start ng-table with pagination
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: 10 // count per page
}, {
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;
orderedData = params.filter() ? $filter('filter')(orderedData, params.filter()) : orderedData;
params.total(orderedData.length); // set total for recalc pagination
$defer.resolve($scope.blocks = orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
// un-check all check boxes
$scope.checkboxes = { 'checked': false, items: {} };
// watch for check all checkbox
$scope.$watch('checkboxes.checked', function(value) {
angular.forEach($scope.blocks, function(item) {
if (angular.isDefined(item.id)) {
$scope.checkboxes.items[item.id] = value;
}
});
});
// watch for data checkboxes
$scope.$watch('checkboxes.items', function(values) {
if (!$scope.blocks) {
return;
}
var checked = 0, unchecked = 0,
total = $scope.blocks.length;
angular.forEach($scope.blocks, function(item) {
checked += ($scope.checkboxes.items[item.id]) || 0;
unchecked += (!$scope.checkboxes.items[item.id]) || 0;
});
if ((unchecked == 0) || (checked == 0)) {
$scope.checkboxes.checked = (checked == total);
}
// grayed checkbox
angular.element(document.getElementById("select_all")).prop("indeterminate", (checked != 0 && unchecked != 0));
}, true);
}, function (error) { // error
$scope.results = [];
// error message display here
});
}
// Call REST API
$scope.load();
/*
|------------------------------
| Delete selected items
|------------------------------
*/
$scope.delete = function() {
var items = [];
// loop through all checkboxes
angular.forEach($scope.blocks, function(item, key) {
if($scope.checkboxes.items[item.id]) {
items.push(item.id); // push checked items to array
}
});
// if at least one item checked
if(items.length > 0) {
// confirm delete
bootbox.confirm("Are you sure to delete this data?", function(result) {
if(result==true) {
for (var i = 0; i < items.length; i++) {
// delete using $http resopurce
Block.delete({id: items[i]}, function (response) { // success
// remove the deleted item from grid here
// show message
}, function (error) { // error
// error message display here
});
}
}
});
}
}; // delete
}); // end controller
HTML Table,
<!-- data table grid -->
<table cellpadding="0" cellspacing="0" border="0" class="table table-striped table-bordered" ng-table="tableParams" show-filter="true">
<tbody>
<tr ng-repeat="block in $data">
<!-- serial number -->
<td data-title="'<?php echo $this->lang->line('sno'); ?>'" style="text-align:center" width="4">{{$index+1}}</td>
<!-- Checkbox -->
<td data-title="''" class="center" header="'ng-table/headers/checkbox.html'" width="4">
<input type="checkbox" ng-model="checkboxes.items[block.id]" />
</td>
<!-- Block Name -->
<td data-title="'<?php echo $this->lang->line('label_cluster_name'); ?>'" sortable="'block_name'" filter="{ 'block_name': 'text' }">
<span ng-if="!block.$edit">{{block.block_name}}</span>
<div ng-if="block.$edit"><input class="form-control" type="text" ng-model="block.block_name" /></div>
</td>
<!-- Description -->
<td data-title="'<?php echo $this->lang->line('label_description'); ?>'" sortable="'description'" >
<span ng-if="!block.$edit">{{block.description}}</span>
<div ng-if="block.$edit"><textarea class="form-control" ng-model="block.description"></textarea></div>
</td>
<!-- Edit / Save button -->
<td data-title="'<?php echo $this->lang->line('label_actions'); ?>'" width="6" style="text-align:center">
<a ng-if="!block.$edit" href="" class="btn btn-inverse btn-sm" ng-click="block.$edit = true"><?php echo $this->lang->line('label_edit'); ?></a>
<a ng-if="block.$edit" href="" class="btn btn-green btn-sm" ng-click="block.$edit = false;update(block)"><?php echo $this->lang->line('label_save'); ?></a>
</td>
</tr>
</tbody>
</table> <!-- table grid -->
You should remove the deleted item from the data collection once the server confirms the deletion.
You can do this manually from within the delete success callback instead of just reloading the complete collection (which is theoretically valid as well but will often be slower).
Then after removing the item from the collection, call the tableParams.reload() method to reload the table so the change is reflected in the table.
You can find a working example of the reload() method right here: http://plnkr.co/edit/QXbrbz?p=info
Hope that helps!
This is working for me:
$scope.deleteEntity = function (entity) {
bootbox.confirm("Are you sure you want to delete this entity ?", function (confirmation) {
if (confirmation) {
$http.delete("/url/" + entity._id)
.success(function (data) {
if (data.status == 1) {
var index = _.indexOf($scope.data, entity);
$scope.data.splice(index, 1);
$scope.tableParams.reload();
} else {
}
});
}
}
);
};
In version 1x of ng-table the following code works. In this example I'm using the MyController as vm approach and user is a $resource class object:
this.removeUser = function (user,i) {
user.$remove().then(function () {
this.tableParams.data.splice(i, 1);
}, function () {
// handle failure
});
});
When called in your HTML table, be sure to pass in $index as the second parameter, eg:
<button class="btn btn-danger btn-xs" ng-click="vm.removeUser(user, $index)" title="Delete User">
<i class="glyphicon glyphicon-trash"></i>
</button>
No need to call tableParams.reload or reload data from the server.