Angular / Ionic - controller only runs once - angularjs

I'm starting out with Angular through the Ionic Framework but I am failing to understand why the controller only runs once i.e. I change state, the controller runs, change to another state and then back again and the controller does not run a second time. This is my state:
$stateProvider.state( 'container.previous', {
url: 'previous',
views: {
main : {
templateUrl : 'views/previous.html',
controller : function( $scope, $cordovaSQLite ){
$scope.firms = [];
$cordovaSQLite.execute(window.db, "SELECT * FROM recent GROUP BY phone ORDER by id DESC").then(function(res) {
for (i = 0; i < res.rows.length; i++) {
$scope.firms.push(res.rows.item(i));
}
}, function (err) {
console.error(err);
});
}
}
},
onStateChangeStart : function(){
backButton = true;
}
});
In another state, if you click on a button related to a "firm", it saves the "firms" data to local storage. The above state shows the firms in which you have previously clicked on. But I cannot figure out how to update the $scope.firms correctly as the controller never runs again.
Can anyone help me out?

You can put the code you want to run in $ionicView.enter:
controller : function( $scope, $cordovaSQLite ){
$scope.$on('$ionicView.enter', function() {
// code to run each time view is entered
});
...
});
See "View LifeCycle and Events": https://ionicframework.com/docs/v1/api/directive/ionView/

Building on #brandyshea's answer, I would like to add if you want to specify no caching in one area/controller/state, and take advantage of the caching in other areas, you can simply use the cache parameter in your $stateProvider for that state.
Disable cache within state provider
$stateProvider.state('myState', {
cache: false,
url : '/myUrl',
templateUrl : 'my-template.html'
})
Alternatively, you can use one of the other methods too:
Disable cache with an attribute
<ion-view cache-view="false" view-title="My Title!">
...
</ion-view>
Disable cache globally
The $ionicConfigProvider can be used to set the maximum allowable views which can be cached, but this can also be use to disable all caching by setting it to 0.
$ionicConfigProvider.views.maxCache(0);
References: http://ionicframework.com/docs/api/directive/ionNavView/ and http://ionicframework.com/docs/api/directive/ionView/

You don't need to disable entire app cache.
If you want to re-run controller every time you enter on it you should clear cache before you leave it:
$scope.$on("$ionicView.afterLeave", function () {
$ionicHistory.clearCache();
});

Ionic has a cache mechanism inside. You can disable caching globally in your config function like this :
$ionicConfigProvider.views.maxCache(0);

Put this in your ion-view.
<ion-view cache-view="false">

Related

How $ionicHistory internally works?

I want to know how $ionicHistory internally works . If i call a function named goBack() inside will it work fine . Or any other tags i need to add in my html code . Please help me out with your suggestions .
i have used both
$scope.goBack = function() {
console.log('Going back');
$ionicViewService.getBackView().go();
}
or
$scope.goBack = function() {
console.log('Going back');
$ionicHistory.goBack();
}
I tried both approach . everytime i am getting same output . you can see where 2nd logout is there , I am trying to navigate from that page to 1st page(1st logout ). But it's coming like this . Please help me out how to resolve this .
Thanks #Sa E Chowdary Finally my code worked
Few changes i made in my js file
.state('app.profile', {
cache: false,// disabled cache
url: './profile',
views: {
'menuContent': {
// templateUrl: 'templates/profile.html',
templateUrl: 'templates/profile.html',
controller: 'ProfileCtrl'
},
'fabContent': {
template: ''
}
}
})
in my controller
setTimeout(
function()
{ $scope.goBack = function() {
console.log('Going back');
$ionicHistory.goBack();
// window.history.go(-1);
};
}, 2000);
Main changes i did is disabled cache otherwise $ionicHistory was not behaving properly .
Again Thanks All
According to the documentation,it will track the views while user navigating in the application....an Ionic app is able to keep track of the previous view, the current view, and the forward view (if there is one).
And it contains some methods you can found in documentation....
coming to your case you need to write some code in your js according to your requirement like whether you want to go to previous view or next view and dont forgot to add or inject the dependency....
you need to use something like this
$ionicHistory.nextViewOptions({
//your code
});
and
$ionicHistory.backView({
//your code
})
you may use $ionicViewService also and you can find there how it will works
yes goBack() will also work in your controller code.
use like this : $ionicHistory.goBack();
Read the documentation

AngularJs UI-Router - Page Refresh $state.current is now empty

I have an Angular application using ui-router and I am having issues whenever I refresh the page. I am using nested views, named views to build the application. Whenever I refresh the page, ui-router doesn't reload the current state and just leaves the page blank.
On page load $state.current is equal to
Object {name: "", url: "^", views: null, abstract: true}
I am reading my navigation from a .json file via $http and looping through the states. So this is what I can show:
stateProvider.state(navElement.stateName, {
url: navElement.regexUrl ? navElement.regexUrl : url,
searchPage: navElement.searchPage, //something custom i added
parent: navElement.parent ? navElement.parent : "",
redirectTo: navElement.redirectTo,
views: {
'subNav#index': {
templateUrl: defaults.secondaryNavigation,
controller: 'secondaryNavigationController as ctrl' //static
},
'pageContent#index': {
template: navElement.templateUrl == null
? '<div class="emptyContent"></div>'
: undefined,
templateUrl: navElement.templateUrl == null
? undefined
: navElement.templateUrl,
controller: navElement.controller == null
? undefined
: navElement.controller + ' as ctrl'
}
}
});
This code gets executed for each item in the nested json object. If there is anything else that would be helpful, let me know.
There is a question: AngularJS - UI-router - How to configure dynamic views with one answer, which shows how to do that.
What is happening? On refresh, the url is evaluated sooner, then states are registered. We have to postpone that. And solution is driven by UI-Router native feature deferIntercept(defer)
$urlRouterProvider.deferIntercept(defer)
As stated in the doc:
Disables (or enables) deferring location change interception.
If you wish to customize the behavior of syncing the URL (for example, if you wish to defer a transition but maintain the current URL), call this method at configuration time. Then, at run time, call $urlRouter.listen() after you have configured your own $locationChangeSuccess event handler.
In a nutshell, we will stop URL handling in config phase:
app.config(function ($urlRouterProvider) {
// Prevent $urlRouter from automatically intercepting URL changes;
// this allows you to configure custom behavior in between
// location changes and route synchronization:
$urlRouterProvider.deferIntercept();
})
And we will re-enable that in .run() phase, once we configured all dynamic states from JSON:
.run(function ($rootScope, $urlRouter, UserService) {
...
// Once the user has logged in, sync the current URL
// to the router:
$urlRouter.sync();
// Configures $urlRouter's listener *after* your custom listener
$urlRouter.listen();
});
There is a plunker from the linked Q & A
I don't know how are all your routes.. but if you refresh a page of a child state, you need to pass all parameters of the parents states to be resolved correctly.

AngularJS reinitialize controller

I have got a controller named newGroupCtrl whose definition is like :
.state('new_group', {
url: '/new_group',
templateUrl: 'templates/new_group.html',
controller: 'newGroupCtrl'
})
.controller('newGroupCtrl', function ($scope, $rootScope,$ionicHistory,$window) {
$rootScope.roomId = $scope.getRoom();
$scope.getRoom = function () {
var date = new Date;
var minutes = date.getMinutes();
var hour = date.getHours();
return 'room_' + hour + '' + minutes;
};
}
I reach this contoller from previous page by :
$window.location.href = ('#/new_group');
That's good until now. $rootScope.roomId variable is initialized in the newGroupCtrl controller properly.
From this new_group page, I navigate to another page. And when I navigate back to this page by calling $window.location.href = ('#/new_group');,
$rootScope.roomId is not initialized again, instead its old value is still there. The state of the newGroupCtrl is preserved.
How can I completely reinitialize newGroupCtrl?
You need to tell state that reload controller each time when URL is getting accessed via browser by just adding adding reload option of state to true like reload: true.
Code
.state('new_group', {
url: '/new_group',
templateUrl: 'templates/new_group.html',
controller: 'newGroupCtrl',
reload: true //will reload controller when state is being access
});
You should use $state.go('new_group') instead of doing $window.location.href = ('#/new_group'); which will ensure that the route changes will recognize by ui-router.
Same SO answer here
Since you are using Ionic Framework (Good Job), you can do this:
.controller('YourCtrl', function($ionicView){
$ionicView.enter(function(){
//code that you want to run, each time the view is active
});
});
Remove the controller from :
.state('new_group', {
url: '/new_group',
templateUrl: 'templates/new_group.html',
})
And add the controller at "new_group.html" page with parent tag of the page like:
<div ng-controller="newGroupCtrl"></div>
Also I found helpful (for Ionic Framework) to use
.state('new_group', {
url: '/new_group',
templateUrl: 'templates/new_group.html',
cache: false
})
Reference to similar question and problems:
Reloading current state - refresh data or in sjm's answer in Reinitialize Controller every time when visiting View - Ionic Framework

Reload data after state transition

I have a problem after calling the $state.transitionTo method.
$state.transitionTo('example', {}, { reload: true});
When I access my view in the first time, the data is correctly loaded. If I manually go back in my application and try to access the same page, the data is reloaded.
But, when I call the $state.transitionTo, the code inside the controller is not executed and myList is not updated.
Here is the code for the controller.
.controller('ExampleCtrl', function
($scope, $state, $stateParams, Service) {
$scope.myList= {};
var exampleCtrl = $scope;
ProdutorService.findAllData($scope.example.idExample).then(function(data){
exampleCtrl.myList = data;
});
}
I think that it might be related to this bug in the $state.reload():
(bug with controllers reinstantiating right now, fixing soon).
https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statereload
Is there any option to enforce executing the controller code or to call a controller function after the state transition?
I am using angularjs with ionic and cordova. It is a mobile application.
I found the solution.
The responsible for the caching was the ionic framework.
By default, Ionic caches all the views for performance. In order to avoid that, it is needed to add a cache:false in the state definition.
.state('example', {
url: "/example",
templateUrl: 'templates/example.html',
controller: 'ExampleCtrl',
cache: false
})
This way, my data is being refreshed.
you can also use the $ionicView.enter listener to update the data, this way the whole view will not need to be recreated.
Scroll Down to View Lifecycle in this blog post

AngularJS - Ionic : execute code in controller when coming back to it

I'm new in AngularJS Community and I'm developping my first app with this Framework.
I created a new controller with this code :
.controller('AccountCtrl', function($scope, $location) {
alert('test');
})
And my route :
.state('app.account', {
url: "/account",
views: {
'menuContent': {
templateUrl: "templates/account.html",
controller: 'AccountCtrl'
}
}
})
The alert popup is shown the first time I access to the controller. But, if I change URL and I come back to AccountCtrl (with a classic html a), the alert popup is not shown again.
Could somebody explain to me why ?
Thanx for your help !
In Ionic Framework views and controllers will be cached by default. You ma add a listener to the views scope to receive a notification when the view is re-active again. For more information see: http://ionicframework.com/docs/api/directive/ionView/
and http://ionicframework.com/docs/api/directive/ionNavView/
You may also disable the cache on a view <ion-view cache-view="false">
.controller('AccountCtrl', function($scope, $location) {
$scope.$on('$ionicView.beforeEnter', function () {
// update campaigns everytime the view becomes active
// (on first time added to DOM and after the view becomes active after cached
alert('test');
});
})`
to reload Controller each time in ui router, use reload: true option on the .state
$stateProvider
.state('app.account', {
url: "/account",
reload: true //forcefully reload route and load controller again
})

Resources