Ng-Table is not binding from NgTableParams with server side data - angularjs

Unable to bind the table with data i.e. collected from service.
Controller code is as:
app.controller('outletTypeController', ['$scope', '$location', '$timeout', 'outletTypesService', '$uibModal', 'NgTableParams', '$q', '$log',
function ($scope, $location, $timeout, outletTypesService, $uibModal, NgTableParams, $q, $log) {
$scope.message = "";
$scope.animationsEnabled = true;
$scope.outletTypes = [];
//To Load Outlet Types in same controller
$scope.LoadOutletTypes = function () {
outletTypesService.getOutletTypes().then(function (results) {
$scope.outletTypes = results.data.Result;
}, function (error) {
var errors = [];
if (response.data != null) {
for (var key in response.data.modelState) {
for (var i = 0; i < response.data.modelState[key].length; i++) {
errors.push(response.data.modelState[key][i]);
}
}
}
$scope.message = "Failed to load data due to:" + errors.join(' ');
});
};
//To Bind OutletType With Options in same controller
$scope.outletTypeWithOptions = function () {
//to set outletTypes
$scope.LoadOutletTypes();
var initialParams = {
count: 2 // initial page size
};
var initialSettings = {
// page size buttons (right set of buttons in demo)
counts: [10, 50, 100],
// determines the pager buttons (left set of buttons in demo)
paginationMaxBlocks: 5,
paginationMinBlocks: 1,
dataset: $scope.outletTypes
};
return new NgTableParams(initialParams, initialSettings);
};
and HTML View Code is as:
<div id="body" ng-controller="outletTypeController">
<table ng-table="outletTypeWithOptions" class="table table-striped" show-filter="true" cellspacing="0" width="100%">
<tr data-ng-repeat="type in $data">
<td title="'Logo'" class="text-center">
<div class="logoImg">
<img src="images/halalpalc.png" width="30" />
</div>
</td>
<td title="'Outlet Type'" filter="{ OTypeName: 'text'}" sortable="'OTypeName'">
{{ type.OTypeName }}
</td>
<td title="'Icon Rated'">I R</td>
<td title="'Icon Unrated'">I U</td>
<td title="'Status'" class="text-center status">
{{ type.IsActive}}
</td>
<td title="'Action'" class="text-center">
<!--<a href="#" class="editAction" data-toggle="modal" data-target="#myModal" title="Edit">
<img src="images/SVG_icons/edit_action.svg" />
</a>-->
<button data-ng-click="open()" class="btn btn-warning">Edit</button>
<!--<img src="images/SVG_icons/close_action.svg" />-->
</td>
</tr>
</table>
</div>
But unable to bind the data, However I try to bind it with Static Data it's properly working.

Here $scope.LoadOutletTypes is an async method call, which will asynchronously populate $scope.outletTypes with results. Rest of the code after LoadOutletTypes method call won't wait for result instead proceeds for execution, which will populate dataset in initialSettings object with null value(If it was unable to load the outlet types in time. But this will work for static data).
Try the below code..
$scope.LoadOutletTypes = function () {
outletTypesService.getOutletTypes().then(function (results) {
$scope.outletTypes = results.data.Result;
$scope.setOutletTypeWithOptions();
}, function (error) {
var errors = [];
if (response.data != null) {
for (var key in response.data.modelState) {
for (var i = 0; i < response.data.modelState[key].length; i++) {
errors.push(response.data.modelState[key][i]);
}
}
}
$scope.message = "Failed to load data due to:" + errors.join(' ');
});
};
$scope.setOutletTypeWithOptions = function () {
var initialParams = {
count: 2 // initial page size
};
var initialSettings = {
// page size buttons (right set of buttons in demo)
counts: [10, 50, 100],
// determines the pager buttons (left set of buttons in demo)
paginationMaxBlocks: 5,
paginationMinBlocks: 1,
dataset: $scope.outletTypes
};
$scope.NgTableParams = new NgTableParams(initialParams, initialSettings);
};
<div id="body" ng-controller="outletTypeController">
<table ng-table="NgTableParams" ng-init="LoadOutletTypes()" class="table table-striped" show-filter="true" cellspacing="0" width="100%">
<tr data-ng-repeat="type in $data">....

Related

Binding scope object to factory object

I am connecting to a websocket feed in a factory, which gives me real time bitcoin price data.
I define service.prices as an object in websocketFactory, and set wsvm.prices = websocketFactory.prices in the controller.
The wsvm.prices.btc property is not updating in the view, but is logging correctly in console.
code:
factory
app.factory('websocketFactory', ['$http', function($http) {
var service = {}
service.prices = {
"btc": 0
}
service.gdax = function() {
const socket = new WebSocket('wss://ws-feed.gdax.com')
var message = {
"type": "subscribe",
"channels": [{
"name": "ticker",
"product_ids": [
"BTC-USD"
]
}, ]
}
socket.addEventListener('open', function(event) {
socket.send(JSON.stringify(message));
})
// Listen for messages
socket.addEventListener('message', function(event) {
var dataObj = JSON.parse(event.data)
if (dataObj.price) {
console.log(dataObj.price) //logging real time data
service.prices.btc = dataObj.price //this should be updating the view
}
});
}
return service
}])
controller
app.controller('WebsocketController', WebsocketController)
WebsocketController.$inject = ['$scope', 'websocketFactory']
function WebsocketController($scope, websocketFactory) {
var wsvm = this
wsvm.prices = websocketFactory.prices
websocketFactory.gdax()
}
view
<div ng-controller="PortfolioController as vm">
<div class="row">
<div class="col-sm-6">
<h2 style="text-align: center;">Account Balances</h2>
</div>
<div class="col-sm-6">
<table class="table">
<thead>
<tr>
<td>24h Change</td>
<td>Total Val USD</td>
<td>BTC Price</td>
</tr>
</thead>
<tbody>
<tr>
<td ng-class="{change_loss: vm.totals.change_24h_usd < 0, change_win: vm.totals.change_24h_usd > 0}"><b>{{vm.totals.change_24h_usd | currency}}</b></td>
<td><b>{{vm.totals.total_usd | currency}}</b></td>
<td ng-controller="WebsocketController as wsvm">{{wsvm.prices.btc}}</td>
</tr>
</tbody>
</table>
</div>
</div>
How to correctly bind factory to controller for real time data?
Changing scope in the socket listener is outside of angular context. Whenever that happens angular needs to be notified to run a digest to update view
Try the following:
app.factory('websocketFactory', ['$http', '$rootScope', function($http, $rootScope) {
......
socket.addEventListener('message', function(event) {
var dataObj = JSON.parse(event.data)
if (dataObj.price) {
console.log(dataObj.price) //logging real time data
$rootScope.$apply(function(){
service.prices.btc = dataObj.price //this should be updating the view
});
}
});
});
I also suggest you look for an angular socket module that will take care of all of this for you internally

angular smart table not working

I am using smart table http://lorenzofox3.github.io/smart-table-website/ and I am trying to follow pipe/ajax plugin example. But its not showing any data. this is what I have in my html
<div ng-controller="AboutCtrl">
<table class="table" st-pipe="mc.callServer" st-table="mc.displayed">
<thead>
<tr>
<th st-sort="id">id</th>
<th st-sort="name">name</th>
<th st-sort="age">age</th>
<th st-sort="saved">saved people</th>
</tr>
<tr>
<th><input st-search="id"/></th>
<th><input st-search="name"/></th>
<th><input st-search="age"/></th>
<th><input st-search="saved"/></th>
</tr>
</thead>
<tbody ng-show="!mc.isLoading">
<tr ng-repeat="row in mc.displayed">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.age}}</td>
<td>{{row.saved}}</td>
</tr>
</tbody>
<tbody ng-show="mc.isLoading">
<tr>
<td colspan="4" class="text-center">Loading ... </td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="text-center" st-pagination="" st-items-by-page="10" colspan="4">
</td>
</tr>
</tfoot>
</table>
</div>
and here is my js
angular.module('eventsApp')
.controller('AboutCtrl', ['Resource', function (service) {
var ctrl = this;
this.displayed = [];
this.callServer = function callServer(tableState) {
ctrl.isLoading = true;
var pagination = tableState.pagination;
var start = pagination.start || 0; // This is NOT the page number, but the index of item in the list that you want to use to display the table.
var number = pagination.number || 10; // Number of entries showed per page.
service.getPage(start, number, tableState).then(function (result) {
ctrl.displayed = result.data;
tableState.pagination.numberOfPages = result.numberOfPages;//set the number of pages so the pagination can update
ctrl.isLoading = false;
});
};
}]).factory('Resource', ['$q', '$filter', '$timeout', function ($q, $filter, $timeout) {
//this would be the service to call your server, a standard bridge between your model an $http
// the database (normally on your server)
var randomsItems = [];
function createRandomItem(id) {
var heroes = ['Batman', 'Superman', 'Robin', 'Thor', 'Hulk', 'Niki Larson', 'Stark', 'Bob Leponge'];
return {
id: id,
name: heroes[Math.floor(Math.random() * 7)],
age: Math.floor(Math.random() * 1000),
saved: Math.floor(Math.random() * 10000)
};
}
for (var i = 0; i < 1000; i++) {
randomsItems.push(createRandomItem(i));
}
//fake call to the server, normally this service would serialize table state to send it to the server (with query parameters for example) and parse the response
//in our case, it actually performs the logic which would happened in the server
function getPage(start, number, params) {
var deferred = $q.defer();
var filtered = params.search.predicateObject ? $filter('filter')(randomsItems, params.search.predicateObject) : randomsItems;
if (params.sort.predicate) {
filtered = $filter('orderBy')(filtered, params.sort.predicate, params.sort.reverse);
}
var result = filtered.slice(start, start + number);
$timeout(function () {
//note, the server passes the information about the data set size
deferred.resolve({
data: result,
numberOfPages: Math.ceil(filtered.length / number)
});
}, 1500);
return deferred.promise;
}
return {
getPage: getPage
};
}]);
and this is what my browser show
Try change this
<div ng-controller="AboutCtrl">
to
<div ng-controller="AboutCtrl as mc">
</script>-->
</script>
</script>
</script>-->
<script>
angular.module('eventsApp', ['smart-table', 'ngSanitize', 'ngRoute'])
.controller('AboutCtrl', ["$scope", "Resource", function ($scope, Resource) {
var ctrl = this;
this.displayed = Resource.GetData();
this.callServer = function callServer(tableState) {
ctrl.isLoading = true;
var pagination = tableState.pagination;
var start = pagination.start || 0; // This is NOT the page number, but the index of item in the list that you want to use to display the table.
var number = pagination.number || 10; // Number of entries showed per page.
Resource.getPage(start, number, tableState).then(function (result) {
ctrl.displayed = result.data;
tableState.pagination.numberOfPages = result.numberOfPages; //set the number of pages so the pagination can update
ctrl.isLoading = false;
});
};
} ]).factory('Resource', ['$q', '$filter', '$timeout', function ($q, $filter, $timeout) {
//this would be the service to call your server, a standard bridge between your model an $http
// the database (normally on your server)
var randomsItems = [];
function GetData() {
function createRandomItem(id) {
var heroes = ['Batman', 'Superman', 'Robin', 'Thor', 'Hulk', 'Niki Larson', 'Stark', 'Bob Leponge'];
return {
id: id,
name: heroes[Math.floor(Math.random() * 7)],
age: Math.floor(Math.random() * 1000),
saved: Math.floor(Math.random() * 10000)
};
}
for (var i = 0; i < 1000; i++) {
randomsItems.push(createRandomItem(i));
}
return randomsItems;
}
//fake call to the server, normally this service would serialize table state to send it to the server (with query parameters for example) and parse the response
//in our case, it actually performs the logic which would happened in the server
function getPage(start, number, params) {
var deferred = $q.defer();
var filtered = params.search.predicateObject ? $filter('filter')(randomsItems, params.search.predicateObject) : randomsItems;
if (params.sort.predicate) {
filtered = $filter('orderBy')(filtered, params.sort.predicate, params.sort.reverse);
}
var result = filtered.slice(start, start + number);
$timeout(function () {
//note, the server passes the information about the data set size
deferred.resolve({
data: result,
numberOfPages: Math.ceil(filtered.length / number)
});
}, 1500);
return deferred.promise;
}
return {
getPage: getPage,
GetData: GetData
};
} ]);
</script>
</head>
<body ng-app="eventsApp">
<div ng-controller="AboutCtrl as mc">
<table class="table" st-pipe="mc.callServer" st-table="mc.displayed">
<thead>
<tr>
<th st-sort="id">id</th>
<th st-sort="name">name</th>
<th st-sort="age">age</th>
<th st-sort="saved">saved people</th>
</tr>
<tr>
<th><input st-search="id"/></th>
<th><input st-search="name"/></th>
<th><input st-search="age"/></th>
<th><input st-search="saved"/></th>
</tr>
</thead>
<tbody ng-show="!isLoading">
<tr ng-repeat="row in mc.displayed">
<td>{{row.id}}</td>
<td>{{row.name}}</td>
<td>{{row.age}}</td>
<td>{{row.saved}}</td>
</tr>
</tbody>
<tbody ng-show="mc.isLoading">
<tr>
<td colspan="4" class="text-center">Loading ... </td>
</tr>
</tbody>
<tfoot>
<tr>
<td class="text-center" st-pagination="" st-items-by-page="10" colspan="4">
</td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>

Add, Remove & Update specific data In JSON in AngularJS

I have pulled data from json file. Now its displayed over DOM.
On HTML Page, I have three option 1) Edit Data 2) Delete Particular Data & 3) Add New Data.
How to perform this using AngularJS Code? i.e. on editing name, it should update my JSON object. On Deleting row, it should delete that row in JSON data. and also If I click on Add New, then entered data will be added to JSON.
My Code is as below.
Importing data through json file and displaying on DOM
.controller('MainCtrl', function ($scope, $http) {
$http.get('data/home.json').
success(function(data, status, headers, config) {
$scope.details = data;
}).
error(function(data, status, headers, config) {
// log error
});
});
Output of this code is correct as below image.
JSON Object as below.
{
"status":"success",
"adformat":[
{
"adformat_id":1,
"name":"Format 1",
"size":"300x250"
},
{
"adformat_id":2,
"name":"Format 2",
"size":"320x250"
},
{
"adformat_id":3,
"name":"Format 3",
"size":"320x480"
}
]
}
I would do it like this:
MainCtrl.js
(function () {
'use strict';
angular
.module('app')
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope', 'MainFactory'];
function MainCtrl($scope, MainFactory) {
$scope.details = MainFactory.details;
function init() {
MainFactory.get();
}
init();
$scope.detailsModel = {
"adformat_id": 1,
"name": "Format 1",
"size": "300x250"
};
$scope.add = function () {
$scope.details.push($scope.detailsModel);
};
$scope.delete = function (index) {
$scope.details.splice(index, 1);
};
$scope.edited = -1;
$scope.editedModel = {
"adformat_id": 0,
"name": "",
"size": ""
};
$scope.edit = function (index) {
$scope.edited = index;
};
$scope.finishEdit = function (index) {
$scope.details[index] = $scope.editedModel;
$scope.edited = -1;
};
}
})();
MainFactory.js
(function () {
'use strict';
angular
.module('app')
.factory('MainFactory', MainFactory);
MainFactory.$inject = [];
function MainFactory() {
var self = this;
self.details = [];
self.get = $http.get('data/home.json')
.then(function (response) {
self.details = response.data;
}).catch(function (error) {
// log error
});
return self;
}
})();
index.html
<div ng-app="app">
<div ng-controller="MainCtrl">
<table>
<tbody>
<tr ng-repeat="details in detail">
<!-- show-->
<td ng-hide="edited === $index">{{detail.adformat_id}}</td>
<td ng-hide="edited === $index">{{detail.name}}</td>
<td ng-hide="edited === $index">{{detail.size}}</td>
<td ng-hide="edited === $index">
<button ng-click="edit($index)">Edit</button>
<button ng-click="delete($index)">Detele</button>
</td>
<!-- Edit-->
<td ng-show="edited === $index">{{detail.adformat_id}}</td>
<td ng-show="edited === $index"><input type="text" ng-model="editedModel.name"></td>
<td ng-show="edited === $index"><input type="number" ng-model="editedModel.size"></td>
<td ng-show="edited === $index">
<button ng-click="finishEdit($index, editedModel)">Save</button>
<button ng-click="delete($index)">Detele</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td>
<button ng-click="add()">Add</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
It is just prototype, not tested, but it should help you to understand idea o two way binding in angular.
Here is my approach to this requirement. Let me know if any further improvement can be added. The entire code can be found at the below URL:
Angular Save, Update and Delete
The sample screenshots from the code can be found here...
controller:
'use strict';
function MainController($scope, SharedService, ngDialog) {
$scope.account_type_selected = "Savings";
$scope.sharedService = SharedService;
$scope.savingsMain = [];
$scope.checkingsMain = [];
$scope.addToCheckingsAccounts = {};
$scope.addToSavingsAccounts = {};
$scope.setAccountType = function (type) {
if (type === "allAccounts") {
$scope.showSavings = true;
$scope.showCheckings = true;
} else if (type === "savingsAccounts") {
$scope.showSavings = true;
$scope.showCheckings = false;
} else if (type === "checkingAccounts") {
$scope.showSavings = false;
$scope.showCheckings = true;
}
$scope.account_type_selected = type;
};
$scope.$watch('savingsMain', function ($scope) {
return $scope.savingsMain;
});
$scope.selectedAccountType = function (showAccount) {
console.log(showAccount);
if (showAccount === "Savings") {
$scope.sharedService.accountType = "Savings";
} else {
$scope.sharedService.accountType = "Checkings";
}
};
$scope.saveAccounts = function () {
if ($scope.sharedService.accountType === "Savings") {
$scope.addToSavingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"date": $scope.sharedService.date,
"maturity": $scope.sharedService.maturity
};
$scope.showSavings = true;
$scope.savingsMain.push($scope.addToSavingsAccounts);
} else {
$scope.addToCheckingsAccounts = {
"account_type": $scope.sharedService.accountType,
"amount": $scope.sharedService.amount,
"bic": $scope.sharedService.BIC,
"iban": $scope.sharedService.IBAN
};
$scope.showCheckings = true;
$scope.checkingsMain.push($scope.addToCheckingsAccounts);
}
ngDialog.close();
};
$scope.deleteDataFromSharedService = function (accountType, item) {
if (accountType === "Savings") {
$scope.savingsMain = _.without($scope.savingsMain, _.findWhere($scope.savingsMain, { date: item }));
} else if (accountType === "Checkings") {
$scope.checkingsMain = _.without($scope.checkingsMain, _.findWhere($scope.checkingsMain, { bic: item }));
}
};
$scope.closeDialog = function () {
ngDialog.close();
};
$scope.accountTypeModel = [];
$scope.prop = {
"type": "select",
"name": "account_type",
"value": $scope.sharedService.accountType,
"accountTypeData": ["Savings", "Checkings"]
};
}
<form ng-controller="MainController">
<div class="page-header">
<h1>Angular-Save-Update-Delete</h1>
</div>
<div class="content-wrapper">
<div class="sidebar">
<table>
<tbody>
<tr>
<td>
<button ng-click="setAccountType('allAccounts')" ng-model="allAccounts" class="ng-pristine ng-untouched ng-valid ng-empty">All</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('savingsAccounts')" ng-model="savingsMain" class="ng-pristine ng-valid ng-not-empty ng-touched">Savings</button>
</td>
</tr>
<tr>
<td>
<button ng-click="setAccountType('checkingAccounts')" ng-model="checkingsMain" class="ng-pristine ng-untouched ng-valid ng-not-empty">Checkings</button>
</td>
</tr>
<tr>
<td>
<button class="create-account-btn-class"
type="button"
ng-dialog="app/views/create-account-template.html"
ng-dialog-data=""
ng-dialog-class="ngdialog-theme-default"
ng-dialog-scope="this"
plain=false
showClose=true
closeByDocument=true
closeByEscape=true
ng-dialog-show-close="false">New Account</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="right-content">
<div id="savingsTemplate" templateurl="app/views/savings.html" ng-show="showSavings" include-template=""></div>
<div id="checkingsTemplate" templateurl="app/views/checkings.html" ng-show="showCheckings" include-template=""></div>
</div>
</div>
</form>

Angularjs Service does not work

I define a Service to share a variable between two controllers, but when i set the variable in a controller and then get this from another controller it does not get the correct value , this is the service:
App.service("ProductService", function () {
var productTotalCount = {};
return {
getproductTotalCount: function () {
return productTotalCount;
},
setproductTotalCount: function (value) {
productTotalCount = value;
}
}
});
and this is the controller which i set productTotalCount:
App.controller("ProductController", function ($scope, $http, $rootScope, ProductService) {
$scope.GetAllProducts = $http.get("GetAllProductsInformation").success(function (data) {
$rootScope.Products = data.Data;
ProductService.setproductTotalCount(data.TotalCount); // i set productTotalCount here and it's value became 19
});
$scope.editProduct = function (data) {
$scope.model = data;
$rootScope.$broadcast('modalFire', data)
}
});
and when i get the productTotalCount in this controller it return object instead of 19 :
App.controller('Pagination', function ($scope, ProductService) {
debugger;
$scope.totalItems = ProductService.getproductTotalCount(); // it should return 19 but return object!!
$scope.currentPage = 1;
$scope.itemPerPage = 8;
});
what is the problem?
EDIT: this is the html, it may help :
<div ng-controller="ProductController" ng-init="GetAllProducts()">
<div class="row" style="margin-top:90px" ng-show="!ShowGrid">
<article class="widget">
<header class="widget__header">
<div class="widget__title">
<i class="pe-7s-menu"></i><h3>ProductList</h3>
</div>
<div class="widget__config">
<i class="pe-7f-refresh"></i>
<i class="pe-7s-close"></i>
</div>
</header>
<div class="widget__content table-responsive">
<table class="table table-striped media-table">
<thead style="background-color:rgba(33, 25, 36,0.1)">
<tr>
<th style="width:40%">edit</th>
<th style="width:30%">Price</th>
<th style="width:30%">ProductName</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="product in Products">
#*<td>{{product.ProductDescription}}</td>*#
<td>
<input class="btn btn-default" style="padding: 14px;background: rgba(0, 0, 0, 0.2)" type="submit" value="Edit" ng-click="editProduct(product)" />
</td>
<td>{{product.Price}}</td>
<td>{{product.ProductName}}</td>
</tr>
</tbody>
</table>
</div>
</article>
</div>
</div>
<div ng-controller="Pagination">
<pagination total-items="totalItems" ng-change="pageChanged()" previous-text="Before" next-text="Next" first-text="First"
last-text="Last" ng-model="currentPage" items-per-page="itemPerPage" max-size="maxSize" class="pagination-sm" boundary-links="true"></pagination>
</div>
From the controller names, I bet the Pagination and ProductController controllers are both instantiated more or less at the same time, BEFORE invoking the .setproductTotalCount() method. If that is the case, then because you are treating the productTotalCount variable as a primitive type (instead of an object) after setting it, the changes do not get reflected between the controllers.
Try the following:
// Change the service to:
App.service("ProductService", function () {
var productTotalCount = {};
return {
getproductTotalCount: function () {
return productTotalCount;
},
setproductTotalCount: function (value) {
productTotalCount.value = value;
}
}
});
// In Pagination controller:
App.controller('Pagination', function ($scope, ProductService) {
debugger;
$scope.totalItems = ProductService.getproductTotalCount(); // this will still be an empty object initially, but when the value is updated in the service, the $scope.totalItems will also be updated
$scope.currentPage = 1;
$scope.itemPerPage = 8;
// this should confirm that changes are being propagated.
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
});
// NOTE: Keep in mind that the real productTotalCount will be stored as $scope.totalItems.value;
});
---- EDIT ----
Per your comment below, it proves that the solution above DOES work. To prove it, change:
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
});
to
$scope.$watch('totalItems', function(newVal) {
console.log('totalItems updated. New Value:', newVal);
console.log($scope.totalItems);
});
At that point, you should see that $scope.totalItems has been updated to:
{ value: 19 };
The issue may be how you're declaring your variable in your service. Because it's a local variable in the function rather than returned object, I believe it will be creating a new variable for each time you inject the service as a dependency. Try making the variable a member of the returned object. E.g.
App.service("ProductService", function () {
return {
productTotalCount: 0,
getproductTotalCount: function () {
return this.productTotalCount;
},
setproductTotalCount: function (value) {
this.productTotalCount = value;
}
}
});

How to remove deleted row in ng-table

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.

Resources