Reload View and Controller in Ionic Framework - angularjs

I am building up an mobile application using Ionic Framework and Cordova Sqlite. I am displaying the data from the sqlite database in an ionic list. Each of the ionic list item has a button to delete the corresponding item from the database. On the click of the button, the data gets deleted from the database, but it continues to appear in the ionic list, until I go back to some other view and come back to it. I need to refresh the view immediately and remove that item from the list also. Also, all my SQL codes are in controller, so I also need to reload the controller, it seems.
app.js
.state('app.cart', {
url: '/cart',
views: {
'menuContent': {
cache: false,
templateUrl: 'templates/cart.html',
controller: 'NFController'
}
}
})
controller.js
.controller('NFController', ['$scope', '$cordovaSQLite','$cordovaToast','$state','$stateParams', function($scope, $cordovaSQLite, $cordovaToast, $state,$stateParams) {
$scope.listItems= [];
$cordovaSQLite.execute(db, 'SELECT * FROM cart ORDER BY id DESC')
.then(
function(res) {
$scope.cartTotal=0;
$scope.crtPP=0;
if (res.rows.length > 0) {
for (var i=0; i<res.rows.length; i++) {
**$scope.crtPP=res.rows.item(i).productPrice*res.rows.item(i).productQuantity;
$scope.cartTotal=$scope.cartTotal+$scope.crtPP;
$scope.CProductName=res.rows.item(i).productName;
$scope.listItems.push(res.rows.item(i));**
}
}
else{
$scope.status = "No Products in the Cart";
}
},
function(error) {
$scope.statusMessage = "Error on loading: " + error.message;
}
);
$scope.remove = function(id) {
$cordovaSQLite.execute(db, 'DELETE from cart WHERE id=?', [id])
.then(function(res) {
//$state.go($state.current, {}, {reload: true});
var current = $state.current;
var params = angular.copy($stateParams);
$state.transitionTo(current, params, { reload: true, inherit: true, notify: true });
$cordovaToast.show('Removed from Cart','short','bottom');
}, function(error) {
console.log(error.message);
})
}
}])
remove() is called on the button click.
Updated Code :
.controller('NFController', ['$scope', '$cordovaSQLite','$cordovaToast', function($scope, $cordovaSQLite, $cordovaToast) {
$scope.listItems= [];
$cordovaSQLite.execute(db, 'SELECT * FROM cart ORDER BY id DESC')
.then(
function(res) {
$scope.cartTotal=0;
$scope.crtPP=0;
if (res.rows.length > 0) {
for (var i=0; i<res.rows.length; i++) {
$scope.listItems.push(res.rows.item(i));
}
cartTotal(); //cartTotal() called initially when the controller loads
console.log("Cart Total : " + $scope.cartTotal);
}
else{
console.log("####console######## NO results found #######"+"Table record #: ");
}
},
function(error) {
}
);
$scope.remove = function(id) {
$cordovaSQLite.execute(db, 'DELETE from cart WHERE id=?', [id])
.then(function(res) {
var index=$scope.listItems.indexOf(id)
$scope.listItems.splice(index,1);
cartTotal(); //CartTotal() called second time
$cordovaToast.show('Removed from Cart','short','bottom');
}, function(error) {
console.log(error.message);
})
console.log(id);
}
function cartTotal()
{
angular.forEach($scope.listItems, function(item, key) {
$scope.crtPP = item.productPrice * item.productQuantity;
$scope.cartTotal += $scope.crtPP;
console.log($scope.cartTotal);
});
}
}])

When you execute the delete in your
$scope.remove = function(id) {
...
}
you don't need to the reload of the view. You can easily remove all this:
var current = $state.current;
var params = angular.copy($stateParams);
$state.transitionTo(current, params, { reload: true, inherit: true, notify: true });
you array of items $scope.listItems= []; should be bound to the view so you simply have to remove the item from the array or reload it and your view will update automatically.
$scope.remove = function(id) {
$cordovaSQLite.execute(db, 'DELETE from cart WHERE id=?', [id])
.then(function(res) {
$scope.listItems = <find the id in the list and remove it>;
$cordovaToast.show('Removed from Cart','short','bottom');
}, function(error) {
console.log(error.message);
})
}
instead of passing the id only to your $scope.remove method you can pass the whole item and use it to find the element in the array so it can be removed:
$scope.remove = function(item) {
$cordovaSQLite.execute(db, 'DELETE from cart WHERE id=?', [item.id])
.then(function(res) {
var index = $scope.listItems.indexOf(item);
$scope.listItems.splice(index, 1);
$cordovaToast.show('Removed from Cart','short','bottom');
}, function(error) {
console.log(error.message);
})
}
and your HTML:
<a class="btn" ng-click="remove(item)">Delete</a>
UPDATE:
Regarding the question in your comments, I would calculate the total using the array $scope.listItems.
I guess you have defined a property in your scope:
$scope.cartTotal = 0;
I would add a function:
function calculateCartTotal()
{
angular.forEach($scope.listItems, function(item, key) {
$scope.cartTotal += item.amount;
});
}
PS: item.amount or whatever your value is.
and recalculate after the splice:
$scope.remove = function(item) {
$cordovaSQLite.execute(db, 'DELETE from cart WHERE id=?', [item.id])
.then(function(res) {
var index = $scope.listItems.indexOf(item);
$scope.listItems.splice(index, 1);
calculateCartTotal();
$cordovaToast.show('Removed from Cart','short','bottom');
}, function(error) {
console.log(error.message);
})
}
If you cannot do that cause you don't have a value item.amount (or similar) you can always re-execute the query in that function and feed $scope.cartTotal.
UPDATE:
function cartTotal()
{
$scope.cartTotal = 0;
angular.forEach($scope.listItems, function(item, key) {
$scope.crtPP = item.productPrice * item.productQuantity;
$scope.cartTotal += $scope.crtPP;
console.log($scope.cartTotal);
});
}

Related

Creating new function in angularjs controller won't work

When creating new function in angularjs controller and assign it to button with ng-click and function is simple,
function toLogin() {
console.log("Entered function");
$state.go('login');
}
I tried with $scope and still does not work.
this is my controller:
'use strict';
angular.module('crudApp').controller('UserController',
['UserService', '$scope','$state', function( UserService, $scope, $state) {
var self = this;
self.user = {};
self.users=[];
self.user.enabled = false;
self.user.confirmationToken = '';
self.loggedUser = null;
self.submit = submit;
self.getAllUsers = getAllUsers;
self.createUser = createUser;
self.updateUser = updateUser;
self.removeUser = removeUser;
self.editUser = editUser;
self.reset = reset;
self.firstNamePattern=/^[A-Z][a-z]*\S$/;
self.lastNamePattern=/^[A-Z][a-z]*\S$/;
self.userNamePattern= /^\S*$/;
self.passwordPattern = /^\S*$/;
self.phonePattern = /^[0-9]+\S$/;
self.successMessage = '';
self.errorMessage = '';
self.done = false;
self.onlyIntegers = /^\d+$/;
self.onlyNumbers = /^\d+([,.]\d+)?$/;
function toLogin() {
console.log('Entered function');
// $state.go('login');
}
function submit() {
console.log('Submitting');
if (self.user.id === undefined || self.user.id === null) {
console.log('Saving New User', self.user);
createUser(self.user);
} else {
updateUser(self.user, self.user.id);
console.log('User updated with id ', self.user.id);
}
}
$scope.moje = function () {
console.log('Submitting');
if (self.user.id === undefined || self.user.id === null) {
console.log('Saving New User', self.user);
createUser(self.user);
} else {
updateUser(self.user, self.user.id);
console.log('User updated with id ', self.user.id);
}
}
function createUser(user) {
console.log('About to create user');
UserService.createUser(user)
.then(
function (response) {
console.log('User created successfully');
self.successMessage = 'User created successfully';
self.errorMessage='';
self.done = true;
self.user={};
$scope.registerForm.$setPristine();
$scope.registerForm.$setUntouched();
// $state.reload();
},
function (errResponse) {
console.error('Error while creating User');
self.errorMessage = 'Error while creating User: ' + errResponse.data.errorMessage;
self.successMessage='';
}
);
}
function updateUser(user, id){
console.log('About to update user');
UserService.updateUser(user, id)
.then(
function (response){
console.log('User updated successfully');
self.successMessage='User updated successfully';
self.errorMessage='';
self.done = true;
$scope.myForm.$setPristine();
},
function(errResponse){
console.error('Error while updating User');
self.errorMessage='Error while updating User '+errResponse.data;
self.successMessage='';
}
);
}
function removeUser(id){
console.log('About to remove User with id '+id);
UserService.removeUser(id)
.then(
function(){
console.log('User '+id + ' removed successfully');
},
function(errResponse){
console.error('Error while removing user '+id +', Error :'+errResponse.data);
}
);
}
function getAllUsers(){
return UserService.getAllUsers();
}
function editUser(id) {
self.successMessage='';
self.errorMessage='';
UserService.getUser(id).then(
function (user) {
self.user = user;
},
function (errResponse) {
console.error('Error while removing user ' + id + ', Error :' + errResponse.data);
}
);
}
function reset(){
self.successMessage='';
self.errorMessage='';
self.user={};
$scope.myForm.$setPristine(); //reset Form
}
}
]);
And and I using ui-routing and this is where I assign controller to my view:
}).state('success',{
url: '/success',
templateUrl: 'partials/successMessage',
controller: 'UserController',
controllerAs: 'sCtrl'
});
And the ftl part of code is here:
<button type="button" ng-click='sCtrl.toLogin()' class="btn btn-primary">Login</button>
It won't even print to console, but when assigning older function it works perfectly, although it is much more complicated. Ps. Sorry for bad clarification at first, I am new to community and still learning a proper way to ask question.
You're not registering the method to the controller, to do that.
Add this below in self.onlyNumbers
self.toLogin = toLogin;
You need to use $scope
$scope.toLogin = function(){
console.log("Entered function");
$state.go('login');
}

Delay loading data in Angular JS

I have code like this
(function (app) {
app.controller('productListController', productListController)
productListController.$inject = ['$scope', 'apiService', 'notificationService', '$ngBootbox', '$filter'];
function productListController($scope, apiService, notificationService, $ngBootbox, $filter) {
$scope.products = [];
$scope.page = 0;
$scope.pagesCount = 0;
$scope.getProducts = getProducts;
$scope.keyword = '';
$scope.search = search;
$scope.deleteProduct = deleteProduct;
$scope.selectAll = selectAll;
$scope.deleteMultiple = deleteMultiple;
function deleteMultiple() {
var listId = [];
$.each($scope.selected, function (i, item) {
listId.push(item.ID);
});
var config = {
params: {
checkedProducts: JSON.stringify(listId)
}
}
apiService.del('/api/product/deletemulti', config, function (result) {
notificationService.displaySuccess('Deleted successfully ' + result.data + 'record(s).');
search();
}, function (error) {
notificationService.displayError('Can not delete product.');
});
}
$scope.isAll = false;
function selectAll() {
if ($scope.isAll === false) {
angular.forEach($scope.products, function (item) {
item.checked = true;
});
$scope.isAll = true;
} else {
angular.forEach($scope.products, function (item) {
item.checked = false;
});
$scope.isAll = false;
}
}
$scope.$watch("products", function (n, o) {
var checked = $filter("filter")(n, { checked: true });
if (checked.length) {
$scope.selected = checked;
$('#btnDelete').removeAttr('disabled');
} else {
$('#btnDelete').attr('disabled', 'disabled');
}
}, true);
function deleteProduct(id) {
$ngBootbox.confirm('Are you sure to detele?').then(function () {
var config = {
params: {
id: id
}
}
apiService.del('/api/product/delete', config, function () {
notificationService.displaySuccess('The product hase been deleted successfully!');
search();
}, function () {
notificationService.displayError('Can not delete product');
})
});
}
function search() {
getProducts();
}
function getProducts(page) {
page = page || 0;
var config = {
params: {
keyword: $scope.keyword,
page: page,
pageSize: 20
}
}
apiService.get('/api/product/getall', config, function (result) {
if (result.data.TotalCount == 0) {
notificationService.displayWarning('Can not find any record.');
}
$scope.products = result.data.Items;
$scope.page = result.data.Page;
$scope.pagesCount = result.data.TotalPages;
$scope.totalCount = result.data.TotalCount;
}, function () {
console.log('Load product failed.');
});
}
$scope.getProducts();
}
})(angular.module('THTCMS.products'));
So my problem is when i loading data the application take me some time to load data.
I need load data as soon as
Is the any solution for this?
Since you are loading data via api call, there will be a delay. To handle this delay, you should display a loading screen. Once the data is loaded, the loading screen gets hidden and your main screen is visible. You can achieve this using $http interceptors.
See : Showing Spinner GIF during $http request in angular
The api-call is almost certainly causing the delay. Data may be received slowly via the api-call so you could display any sort of loading text/image to notify the use that the data is being loaded.
If u want the data ready at the time when controller inits, u can add a resolve param and pass the api call as a $promise in the route configuration for this route.

Deleting row with scope array leaves blank page

Trying to refresh the view with scope array after deleting a row from database I have no luck:
$scope.remove = function() {
var x = document.getElementById("name").textContent;
$cordovaSQLite.execute(db, 'DELETE from table WHERE name=?', [x])
.then(function(res) {
var index = $scope.listItems.indexOf(x);
$scope.listItems.splice(index, 1);
}, function(error) {
console.log(error.message);
})
};
Delete succeeds but leaves me a blank page. To refresh in my Ionic app I have to go to another page and back:
$scope.showConfirm = function () {
var x = document.getElementById("name").textContent;
var confirmPopup = $ionicPopup.confirm({
title: 'Deleting Journal Entry',
template: 'Are you sure you want to delete this item ?'
});
confirmPopup.then(function (res) {
if (res) {
var query = "DELETE FROM chocolates where name = ?";
$cordovaSQLite.execute(db, query, [x]);
$state.go($state.current, $stateParams, {reload: true, inherit: false});
console.log(x);
} else {
console.log('You are not sure');
};
});
};
This code also succeeds deleting the row but the refresh function is not working. I tried answers from alternative 1 and alternative 2.
if (res) {
$ionicPlatform.ready(function () {
$scope.chocolates = [];
var query = "DELETE FROM chocolates where name = ?";
$cordovaSQLite.execute(db, query, [x]);
$cordovaSQLite.execute(db, 'SELECT * FROM chocolates ORDER BY choc_id DESC LIMIT 1', []).then(function (res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
$scope.chocolates.push(res.rows.item(i));
}
}
}, function (err) {
console.error(err);
});
$scope.$apply();
});
} else {
console.log('You are not sure');
};
This is the solution.

AngularJs UI Grid rebind from Modal

I have a main controller in which I load data into a "angular-ui-grid" and where I use a bootstrap modal form to modify detail data, calling ng-dlbclick in a modified row template :
app.controller('MainController', function ($scope, $modal, $log, SubjectService) {
var vm = this;
gridDataBindings();
//Function to load all records
function gridDataBindings() {
var subjectListGet = SubjectService.getSubjects(); //Call WebApi by a service
subjectListGet.then(function (result) {
$scope.resultData = result.data;
}, function (ex) {
$log.error('Subject GET error', ex);
});
$scope.gridOptions = { //grid definition
columnDefs: [
{ name: 'Id', field: 'Id' }
],
data: 'resultData',
rowTemplate: "<div ng-dblclick=\"grid.appScope.editRow(grid,row)\" ng-repeat=\"(colRenderIndex, col) in colContainer.renderedColumns track by col.colDef.name\" class=\"ui-grid-cell\" ng-class=\"{ 'ui-grid-row-header-cell': col.isRowHeader }\" ui-grid-cell></div>"
};
$scope.editRow = function (grid, row) { //edit row
$modal.open({
templateUrl: 'ngTemplate/SubjectDetail.aspx',
controller: 'RowEditCtrl',
controllerAs: 'vm',
windowClass: 'app-modal-window',
resolve: {
grid: function () { return grid; },
row: function () { return row; }
}
});
}
});
In the controller 'RowEditCtrl' I perform the insert/update operation and on the save function I want to rebind the grid after insert/update operation. This is the code :
app.controller('RowEditCtrl', function ($modalInstance, $log, grid, row, SubjectService) {
var vm = this;
vm.entity = angular.copy(row.entity);
vm.save = save;
function save() {
if (vm.entity.Id === '-1') {
var promisePost = SubjectService.post(vm.entity);
promisePost.then(function (result) {
//GRID REBIND ?????
}, function (ex) {
$log.error("Subject POST error",ex);
});
}
else {
var promisePut = SubjectService.put(vm.entity.Id, vm.entity);
promisePut.then(function (result) {
//row.entity = angular.extend(row.entity, vm.entity);
//CORRECT WAY?
}, function (ex) {
$log.error("Subject PUT error",ex);
});
}
$modalInstance.close(row.entity);
}
});
I tried grid.refresh() or grid.data.push() but seems that all operation on the 'grid' parameter is undefinied.
Which is the best method for rebind/refresh an ui-grid from a bootstrap modal ?
I finally solved in this way:
In RowEditCtrl
var promisePost = SubjectService.post(vm.entity);
promisePost.then(function (result) {
vm.entity.Id = result.data;
row.entity = angular.extend(row.entity, vm.entity);
$modalInstance.close({ type: "insert", result: row.entity });
}, function (ex) {
$log.error("Subject POST error",ex);
});
In MainController
modalInstance.result.then(function (opts) {
if (opts.type === "insert") {
$log.info("data push");
$scope.resultData.push(opts.result);
}
else {
$log.info("not insert");
}
});
The grid that received inside RowEditCtrl is not by reference, so it wont help to refresh inside the RowEditCtrl.
Instead do it right after the modal promise resolve in your MainController.
like this:
var modalInstance = $modal.open({ ...});
modalInstance.result.then(function (result) {
grid.refresh() or grid.data.push()
});

error performing a get request

I am trying to perform a get request, in the post request everything is OK, I can see that in the post request all I do it's been save, once I refresh the page I am printing in the console the items saved by the post request, but those items aren't been return with the get I am doing.
here is where everything begins, I have a list of items here with the option to checked or unchecked the items in the list
<ion-item ng-repeat="sport in sports" ng-click="toggleSportSelection(sport)">
{{:: sport.name}}
</ion-item>
all the items are checked = true by default, so what I am saving, are the items with checked = false, the items checked = true you can see them here
<div ng-show="sport.checked" ng-repeat="sport in sports">
{{sport.name}}
</div>
this is what I have in the controller
.controller('SportsController', function($scope, SportsFactory) {
SportsFactory.getSportChecked(customer).then(function(sportChecked) {
_.each(sports, function(sport) {
var sportIds = _.pluck(sport, 'id'),
intersectedSports = _.intersection(sport.id, sportChecked),
checkedSportObjects = _.filter(sport, function(sportObj) {
return _.includes(intersectedSports, sportObj);
});
_.each(checkedSportObjects, function(sport) {
$scope.sports.push(sport);
});
});
}, function(err) {
console.log(err);
});
$scope.toggleSportSelection = function(sport) {
var params = {};
params.user = $scope.customer.customer;
params.sport = sport.id;
sport.checked = !sport.checked;
SportsFactory.setSportChecked(params);
};
// this is what puts the sports on checked = true
if (sports.length) {
$scope.sports = _.map(sports, function(sport) {
sport.checked = true;
return sport;
});
}
and this is the service / factory
.factory('SportsFactory', function($http, $q, AuthFactory,
LocalForageFactory, CONSTANT_VARS) {
return {
getSportChecked: function(customer) {
var defer = $q.defer(),
user,
rejection = function(err) {
console.log(err);
defer.reject(err);
};
LocalForageFactory.retrieve(CONSTANT_VARS.LOCALFORAGE_SPORTS_CHECKED)
.then(function(sportChecked) {
user = customer.customer;
if (!_.isNull(sportChecked)) {
defer.resolve(sportChecked);
}else {
$http.get(CONSTANT_VARS.BACKEND_URL + '/sports/getChecked/' + user)
.success(function(sportChecked) {
LocalForageFactory.set(CONSTANT_VARS.LOCALFORAGE_SPORTS_CHECKED, sportChecked);
defer.resolve(sportChecked);
})
.error(rejection);
}
}, rejection);
return defer.promise;
}
});
I am working along with NodeJS, so if you want the code I have in that part just let me know, so far I think that the issue I have is in the front end part, in the controller.

Resources