Ionic list, how to update a specific item? - angularjs

I am developing an ios app with angularjs and ionic.
I don't know how to get a specific item in a list to be updated ?
Here is my view :
mesReservations.html
<ion-view cache-view="false" view-title="Mes reservations">
<ion-pane>
<ion-content class="padding">
<ion-list>
<ion-item ng-repeat="reservation in listeReservations" class="item item-button-right">
{{reservation.nomLoisir}}
<p>{{reservation.dateReservation}} |{{reservation.heureReservation}} | {{reservation.nbrpersonne}} pers</p>
<p>{{reservation.etatResa}}</p>
<div class="buttons">
<button class="button button-small" ng-click="annulerReservation(reservation.idReservation)">
<i class="icon ion-close"></i>
</button>
</div>
</ion-item>
</ion-list>
<ion-infinite-scroll ng-if="!theEnd" on-infinite="loadMore()" distance="50%"></ion-infinite-scroll>
</ion-content>
</ion-pane>
</ion-view>
my controller : mesReservetionsController.js
(function () {
'use strict';
angular
.module('starter')
.controller('MesReservationsController', MesReservationsController);
MesReservationsController.$inject = ['ReservationService', '$scope', '$state'];
function MesReservationsController (ReservationService, $scope, $state) {
$scope.listeReservations = [];
$scope.theEnd = false;
var page = 0;
$scope.enable= true;
//chargerReservations();
$scope.loadMore = function () {
page++;
ReservationService.listReservation(page)
.then(function (result) {
if(result.params.reservation.length > 0){
angular.forEach(result.params.reservation, function (value, key) {
$scope.listeReservations.push(value);
})
}
else {
$scope.theEnd = true;
}
})
.finally(function () {
$scope.$broadcast("scroll.infiniteScrollComplete");
});
}
/*$scope.confirmerReservation = function (idReservation) {
ReservationService.confirmerReservation(idReservation).then(function (res) {
if(res.statut==="1"){
chargerReservations();
alert(res.message);
}
});
};*/
$scope.partagerReservation = function (idReservation) {
alert("That's to share your reservation");
}
$scope.showMap = function () {
alert("That shall show map");
}
$scope.changerReservation = function (idReservation) {
debugger
$state.go('detailReservation', {idReservation: idReservation});
}
$scope.detailLoisir = function () {
alert("that shall show detail");
}
$scope.annulerReservation = function (idReservation) {
debugger
$scope.enable= false;
ReservationService.annulerReservation(idReservation).then(function (res) {
if(res.statut==="1"){
alert(res.message);
}
});
};
function chargerReservations (page) {
debugger
ReservationService.listReservation(page).then(function (res) {
if(res.statut==="1"){
$scope.$apply(function () {
$scope.listeReservations = res.params.reservation;
})
}
});
}
}
})();
What I need is to update {{reservation.etatResa}} when ReservationService.annulerReservation() is called without having to reload the list from server?

Pass the entire object to your method instead of just the id:
ng-click="annulerReservation(reservation)"
Then you can simply modify it as you want (for example when the ReservationService.annulerReservation call has succeeded):
reservation.etatResa = 'Whatever';
Don't forget to change so you pass the id to the service (if that is what it needs):
ReservationService.annulerReservation(reservation.idReservation).then( ... )

Related

$scope not updating when I go between pages

I am working on an application that goes from template A to template B back to template A. On template A the user click on a button to get to template B. On template B the user add in an amount then hits submit. The program then goes back to template A and displays what was inputted in template B, but the number submitted is not updated in the scope and appears as null. For some reason when I start the application from Template B to Template A the scope is updated.
I am using a factory
.factory('myService', function(){
var budget = {
limit: null
};
function set(data){
budget.limit = data;
}
function get(){
return budget.limit;
}
return{
set: set,
get: get,
print: console.log(budget.limit)
}
})
Here is my code for Template A called BudgetCalc
<ion-view view-title="BudgetCalc">
<ion-content class="padding">
<button>Start Budgeting</button>
<h2>Your Limit is {{limit}}</h2>
</ion-content>
</ion-view>
And Template B named addBuget
<ion-view view-title="Add a Budget">
<ion-content>
<label class="item item-input">
<span class="input-label">Set Spending Limit</span>
<input type="number"ng-model="limit">
</label>
<button ui-sref="tab.budget" ng-click="setLimit(limit)">Submit</button>
<br><h2>Your Limit is: {{limit}}</h2>
</ion-content>
</ion-view>
Here is are my Controllers for the two templates
.controller('BudgetCtrl', function($scope, myService) {
$scope.limit = myService.get();
console.log("This is your limit " + $scope.limit);
})
.controller('SetLimitCtrl', function($scope, myService){
$scope.setLimit = function(limit){
if (limit != null) {
myService.set(limit);
console.log(myService.print);
}
}
})
You can share data between controllers using localstorage
.controller('SetLimitCtrl', function($scope, $localstorage){
$scope.setLimit = function(limit){
if (limit != null) {
$localstorage.set("limit",limit);
console.log($localstorage.get("limit"));
}
}
})
.controller('BudgetCtrl', function($scope, $localstorage) {
$scope.limit = $localstorage.get("limit");
console.log("This is your limit " + $scope.limit);
//// Dont forgot to clear limit when you complete the further process
})
Factory Localsoarage:
.factory('$localstorage', ['$window', function ($window) {
return {
set: function (key, value) {
$window.localStorage[key] = value;
},
get: function (key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function (key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function (key, nulled) {
nulled = '[]';
try {
return JSON.parse($window.localStorage[key] || '[]');
} catch (e) {
}
},
delete: function (key) {
$window.localStorage.removeItem(key);
},
};
}])

Pass object back from ionic model service

I have created a factory for a modal that pulls in an array(list) and I have a ng-click where I get the index and then get the object I want to pass the object back to my controller so I can then use it.
I not sure how I will pass the object back to the controller.
This is the function in my service that fires the open() for the modal and I am passing it the model that i receive from a rest call.
function CopyModalService($ionicModal, $rootScope) {
var $scope = $rootScope.$new(),
myModalInstanceOptions = {
scope: $scope,
animation: 'slide-in-up'
};
return {
open: open
};
function open(model) {
$ionicModal.fromTemplateUrl('templates/copy-modal.html',
myModalInstanceOptions)
.then(function (modalInstance) {
$scope.model = model;
$scope.addCopyCertificate = function(index){
console.log('click', $scope.model[index]);
};
$scope.close = function () {
closeAndRemove(modalInstance);
};
return modalInstance.show(model);
});
}
This is the html in the modal so you can get the picture
<ul class="list">
<li class="item row" ng-repeat="item in model">
<span class="col col-67">{{item.installerReference}}</span>
<span class="col">
<button class="button button-calm button-calm-search ion-ios-arrow-down"
ng-click="addCopyCertificate($index)"></button>
</span>
</li>
</ul>
When I click the button in the html addCopyCertificate() it all appears fine but how do I pass that back to the controller.
In my controller I am using it like this: (which is working)
if (res.length) {
CopyModalService.open(res);
}else{
Alert.showAlert('No matching certificates');
....
}
what about $rootScope.$broadcast? something like:
function CopyModalService($ionicModal, $rootScope) {
var $scope = $rootScope.$new(),
myModalInstanceOptions = {
scope: $scope,
animation: 'slide-in-up'
};
return {
open: open
};
function open(model) {
$ionicModal.fromTemplateUrl('templates/copy-modal.html',
myModalInstanceOptions)
.then(function (modalInstance) {
$scope.model = model;
$scope.addCopyCertificate = function(index){
console.log('click', $scope.model[index]);
$rootScope.$broadcast('update-controller',$scope.model[index]);
};
$scope.close = function () {
closeAndRemove(modalInstance);
};
return modalInstance.show(model);
});
}
and then when you want to get the value ..attach the listener with $rootScope.$on('') (or better $scope.$on()) ..something like
if (res.length) {
CopyModalService.open(res);
$scope.$on('update-controller',function(event, data){
console.log(data);
});
}else{
Alert.showAlert('No matching certificates');
....
}

Angular ion-radio filter data from external db

I have 2 tables in Azure db 1 called team and 1 called league, the id in league is also associated to a team e.g. team a belongs to leagueID 1. I am trying to use ion-radio so users can choose their team but filter it by the league but cannot work out whether ng-if or filter is the best option. I have set up a service to call the data from azure: services.js
.factory('League', function ($ionicPopup) {
var url = 'http://';
var client = new WindowsAzure.MobileServiceClient(url);
var LeagueTable = client.getTable('League');
function refreshDisplay() {
return LeagueTable
.read()
.then(createList, handleError);
}
function createList(items) {
return items;
}
function handleError(error) {
var LeagueName = error + (error.request ? ' - ' + error.request.status : '');
console.error(LeagueName);
console.log('error', error.request.status);
if (error.request.status == '0' || error.request.status == '404') {
$ionicPopup.alert({
title: 'Connection Failure',
template: 'Connection with backend can not be established.'
});
}
}
return {
all: function () {
return refreshDisplay();
},
};
})
.factory('Team', function ($ionicPopup) {
var url = 'http://';
var client = new WindowsAzure.MobileServiceClient(url);
var TeamTable = client.getTable('Team');
function refreshDisplay() {
return TeamTable
.read()
.then(createTeamList, handleError);
}
function createTeamList(items) {
return items;
}
function handleError(error) {
var text = error + (error.request ? ' - ' + error.request.status : '');
console.error(text);
console.log('error', error.request.status);
if (error.request.status == '0' || error.request.status == '404') {
$ionicPopup.alert({
title: 'Connection Failure',
template: 'Connection with backend can not be established.'
});
}
}
return {
all: function () {
return refreshDisplay();
},
}
});
The controller at the moment just pulls back all the teams, controller.js:
.controller('LeagueCtrl', function ($scope, $window, League) {
$scope.doRefresh = function () {
League.all().then(function (newList) {
$scope.items = newList;
$scope.$broadcast('scroll.refreshComplete');
$scope.$apply();
});
};
$scope.doRefresh();
console.log(League);
$scope.League;
})
.controller('TeamCtrl', function ($scope, $window, Team) {
$scope.doRefresh = function () {
Team.all().then(function (newList) {
$scope.items = newList;
$scope.$broadcast('scroll.refreshComplete');
$scope.$apply();
return $scope.items
});
};
$scope.doRefresh();
});
And the HTML teams.html:
<ion-view view-title="Choose your Team">
<ion-nav-buttons side="primary">
</ion-nav-buttons>
<ion-content>
<ion-refresher pulling-text="Pull to refresh..."
on-refresh="doRefresh()">
</ion-refresher>
<div ng-controller="SportCtrl">
<h2> Choose sport</h2>
<ion-radio ng-model="item.complete" ng-repeat="item in items" > {{item.text}}</ion-radio>
</div>
<div ng-controller="LeagueCtrl">
<h2> Choose Conference</h2>
<ion-radio ng-model="item.complete" ng-repeat="item in items"> {{item.LeagueName}}</ion-radio>
</div>
<div ng-controller="TeamCtrl">
<h2> Choose Team</h2>
<ion-radio ng-model="item.complete" ng-repeat="item in items"> {{item.TeamName}}</ion-radio>
</div>
<div >
<button class="button button-large-font-size button-block button- assertive" ui-sref="app.home">Booyah</button>
</div>
</ion-content>
</ion-view>
Can anyone point me in the right direction
As the scopes in different controller are separate, so there is a simple solution, you can put the League and Team in a same controller and in a same scope, then you can custom a filter function in your controller to achieve your requirements.
Generally:
<div ng-controller="LeagueTeamCtrl">
<h2> Choose Conference</h2>
<ion-radio ng-model="data.league_id" ng-repeat="item in league" ng-value="item.id">{{item.LeagueName}}</ion-radio>
<h2> Choose Team</h2>
<ion-radio ng-model="data.team_id" ng-repeat="item in team" ng-value="item.id">{{item.TeamName}}</ion-radio>
</div>
And the custom filter function:
$scope.myFilter = function (item) {
return item.leagueId === $scope.league_id ;
};
And you can refer to the full example at http://codepen.io/liuguixiao/pen/ZpYLAB

won't remove automatically after it deleted from localstorage

First, here's the code
controller.js
.controller('FavoritesController', ['$scope', 'dishes', 'favorites', 'favoriteFactory', 'baseURL', '$ionicListDelegate', '$ionicPopup', '$ionicLoading', '$timeout', '$localStorage', function ($scope, dishes, favorites, favoriteFactory, baseURL, $ionicListDelegate, $ionicPopup, $ionicLoading, $timeout, $localStorage) {
$scope.baseURL = baseURL;
$scope.shouldShowDelete = false;
$scope.favorites = favorites;
$scope.dishes = dishes;
console.log($scope.dishes, $scope.favorites);
$scope.toggleDelete = function () {
$scope.shouldShowDelete = !$scope.shouldShowDelete;
console.log($scope.shouldShowDelete);
}
$scope.deleteFavorite = function (index) {
var confirmPopup = $ionicPopup.confirm({
title: 'Confirm Delete',
template: 'Are you sure you want to delete this item?'
});
confirmPopup.then(function (res) {
if (res) {
console.log('Ok to delete');
favoriteFactory.deleteFromFavorites(index);
var old_favorite = JSON.parse($localStorage.get('favorites'));
var leng = Object.keys(old_favorite).length;
for (var i = 0; i < leng; i++) {
if (Object.keys(old_favorite)[i] == index) {
console.log("Deleted from localstorage! " + Object.keys(old_favorite)[i]);
old_favorite.splice(old_favorite.indexOf(index), 1);
$localStorage.storeObject('favorites', old_favorite);
}
}
} else {
console.log('Canceled delete');
}
});
$scope.shouldShowDelete = false;
}
}])
services.js
.factory('favoriteFactory', ['$resource', 'baseURL', function ($resource, baseURL) {
var favFac = {};
var favorites = [];
favFac.addToFavorites = function (index) {
for (var i = 0; i < favorites.length; i++) {
if (favorites[i].id == index)
return;
}
favorites.push({id: index});
};
favFac.deleteFromFavorites = function (index) {
for (var i = 0; i < favorites.length; i++) {
if (favorites[i].id == index) {
favorites.splice(i, 1);
console.log("Deleted !" + index);
}
}
}
favFac.getFavorites = function () {
return favorites;
};
return favFac;
}])
favorites.html
<ion-view view-title="My Favorites">
<ion-nav-buttons side="secondary">
<div class="buttons">
<button class="button button-icon icon ion-ios-minus-outline"
ng-click="toggleDelete()"></button>
</div>
</ion-nav-buttons>
<ion-content>
<ion-list show-delete="shouldShowDelete">
<ion-item ng-repeat="dish in dishes | favoriteFilter:favorites" href="#/app/menu/{{dish.id}}" class="item-thumbnail-left" on-swipe-left="deleteFavorite(dish.id)">
<img ng-src="{{baseURL+dish.image}}" on-swipe-left="deleteFavorite(dish.id)">
<h2>{{dish.name}}
<span style="font-size:75%">{{dish.price | currency}}</span>
<span class="badge badge-assertive">{{dish.label}}</span></h2>
<p>{{dish.description}}</p>
<ion-delete-button class="ion-minus-circled"
ng-click="deleteFavorite(dish.id)">
</ion-delete-button>
</ion-item>
</ion-list>
</ion-content>
</ion-view>
app.js
.state('app.favorites', {
url: '/favorites',
views: {
'mainContent': {
templateUrl: 'templates/favorites.html',
controller:'FavoritesController',
resolve: {
dishes: ['menuFactory', function(menuFactory){
return menuFactory.query();
}],
favorites: ['favoriteFactory', function(favoriteFactory) {
return favoriteFactory.getFavorites();
}]
}
}
}
})
So, after I attempt to use the deleteFavorite Function from the controller.js and the index inside the localstorage was success deleted, the data on the favorites.html couldn't updated, it couldn't deleted from the favorties.html immediately.
I need to refresh my browser first to show the up-to-date list based on the localstorage.
I hope that I can show the up-to-date data based on the localstorage data without refresh the page.
Did I make something wrong on here?
Thank you in advance!

Passing data from ionic/angular modal using separate template html file

I'm developing a simple Ionic mobile app although the answer likely lies with Angular. The app is really simple, displays a list of employees with an Add button which displays a modal, lets the user enter some details, click Save and it's persists the data to a back-end Firebase store. It has 1 controller and a simple service. Initially I had the template html for the modal inside script tags inside the index.html and it all worked fine. When I decided to structure things out and put the modal template in a separate html file, suddenly the data object assigned to ng-modal via the input boxes no longer passes any data to the event handler to save the data, instead it's always undefined. Everything else works as it should, the modal displays ok, the event handlers are calling the right functions etc. The only change is moving the input template to a separate file. I know it's likely something really simple but can't for the life of me work out why and can't find any info about it anywhere else.
Template HTML file for the modal :
<ion-list>
<h1>Add Employee</h1>
<div class="list list-inset">
<ion-item>
<label class="item item-input">
<input type="text" placeholder="Employee Name" ng-model="data.employeeName">
</label>
<label class="item item-input">
<input type="text" placeholder="Employee Age" ng-model="data.employeeAge">
</label>
</ion-item>
<button class="button button-outline button-block button-balanced"
ng-click="addEmployee(true, data)">
Save & Add Another
</button>
<button class="button button-outline button-block button-positive"
ng-click="addEmployee(false, data)">
Save
</button>
<button class="button button-outline button-block button-assertive"
ng-click="closeAddModal()">
Cancel
</button>
</ion-list>
</ion-modal-view>
addEmployee event - data parameter is now always undefined. Worked fine with embedded template :
$scope.addEmployee = function(retainModal, data) {
var employee = {employeeName:data.employeeName,
employeeAge:data.employeeAge};
employeeService.saveEmployee(employee);
if (! retainModal) {
$scope.closeAddModal();
};
data.employeeName = "";
data.employeeAge = "";
};
Based on this question and other needs I create a service that can be useful.
See this post: Ionic modal service or see in operation: CodePen
(function () {
'use strict';
var serviceId = 'appModalService';
angular.module('app').factory(serviceId, [
'$ionicModal', '$rootScope', '$q', '$injector', '$controller', appModalService
]);
function appModalService($ionicModal, $rootScope, $q, $injector, $controller) {
return {
show: show
}
function show(templateUrl, controller, parameters) {
// Grab the injector and create a new scope
var deferred = $q.defer(),
ctrlInstance,
modalScope = $rootScope.$new(),
thisScopeId = modalScope.$id;
$ionicModal.fromTemplateUrl(templateUrl, {
scope: modalScope,
animation: 'slide-in-up'
}).then(function (modal) {
modalScope.modal = modal;
modalScope.openModal = function () {
modalScope.modal.show();
};
modalScope.closeModal = function (result) {
deferred.resolve(result);
modalScope.modal.hide();
};
modalScope.$on('modal.hidden', function (thisModal) {
if (thisModal.currentScope) {
var modalScopeId = thisModal.currentScope.$id;
if (thisScopeId === modalScopeId) {
deferred.resolve(null);
_cleanup(thisModal.currentScope);
}
}
});
// Invoke the controller
var locals = { '$scope': modalScope, 'parameters': parameters };
var ctrlEval = _evalController(controller);
ctrlInstance = $controller(controller, locals);
if (ctrlEval.isControllerAs) {
ctrlInstance.openModal = modalScope.openModal;
ctrlInstance.closeModal = modalScope.closeModal;
}
modalScope.modal.show();
}, function (err) {
deferred.reject(err);
});
return deferred.promise;
}
function _cleanup(scope) {
scope.$destroy();
if (scope.modal) {
scope.modal.remove();
}
}
function _evalController(ctrlName) {
var result = {
isControllerAs: false,
controllerName: '',
propName: ''
};
var fragments = (ctrlName || '').trim().split(/\s+/);
result.isControllerAs = fragments.length === 3 && (fragments[1] || '').toLowerCase() === 'as';
if (result.isControllerAs) {
result.controllerName = fragments[0];
result.propName = fragments[2];
} else {
result.controllerName = ctrlName;
}
return result;
}
} // end
})();
Usage:
appModalService
.show('<templateUrl>', '<controllerName> or <controllerName as ..>', <parameters obj>)
.then(function(result) {
// result from modal controller: $scope.closeModal(result) or <as name here>.closeModal(result) [Only on template]
}, function(err) {
// error
});
You can use another service to centralize the configuration of all modals:
angular.module('app')
.factory('myModals', ['appModalService', function (appModalService){
var service = {
showLogin: showLogin,
showEditUser: showEditUser
};
function showLogin(userInfo){
// return promise resolved by '$scope.closeModal(data)'
// Use:
// myModals.showLogin(userParameters) // get this inject 'parameters' on 'loginModalCtrl'
// .then(function (result) {
// // result from closeModal parameter
// });
return appModalService.show('templates/modals/login.html', 'loginModalCtrl as vm', userInfo)
// or not 'as controller'
// return appModalService.show('templates/modals/login.html', 'loginModalCtrl', userInfo)
}
function showEditUser(address){
// return appModalService....
}
}]);
You need to attach your models to the scope:
$scope.data.employeeName = "";
$scope.data.employeeAge = "";
...and similar every time you reference them.

Resources