I am learning AngularJS and ionic framework using this tutorial:
http://www.htmlxprs.com/post/12/tutorial-on-using-parse-rest-api-and-ionic-framework-together
Everything works well up until the point when I create a new item in the createTodo state and then call $state.go('todos') to go back to my items list, here is the code for the create Todo Controller:
.controller('TodoCreateController', ['$scope', 'Todo', '$state', function($scope, Todo, $state) {
$scope.todo = {};
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$state.go('todos', {}, {reload: true});
});
}
}])
Here is the code for the item list controller:
.controller('TodoListController', ['$scope', 'Todo', '$state', function($scope, Todo) {
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
$scope.deleteItem = function(item) {
Todo.delete(item.objectId);
$scope.items.splice($scope.items.indexOf(item), 1);
};
}])
Here are the states configured
.config(function($stateProvider) {
$stateProvider.state('todos', {
url: '/todos',
controller: 'TodoListController',
templateUrl: 'views/todos.html'
}).state('createTodo', {
url: '/todo/new',
controller: 'TodoCreateController',
templateUrl: 'views/create-todo.html'
});
})
When the application starts, the method of the TodoListController is invoked thanks to the last line added and the end of the .run method in the main app.js (or at least thats my understanding):
.run(function($ionicPlatform, $state) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
$state.go('todos');
})
My problem is that, as soon as the new item is created and I invoke $state.go('todos') from the TodoCreateController, it takes me back to the item list but the new item is not there and the method of the TodoListController is never invoked, therefore leaving the list outdated.
How can I refresh the list in the 'todos' state after a new item has been created?
I found a rather elegant solution:
Inside my TodoListController I define an event listener like this:
$rootScope.$on('todo:listChanged', function() {
$scope.updateList();
});
then comes the updateList() method
$scope.updateList = function() {
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
};
And finally in the TodoCreateController I $emit the event upwards as soon as the item is created and right before changing state
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$scope.$emit('todo:listChanged');
$state.go('todos');
});
};
And voila! The list updates accordingly and I can now use the same event if I delete or update a list item
I've encountered this and similar problems and it turned out that ionic view caching often was the reason for not calling the controller code when returning to a cached view.
Possible Solution
When separating controller code into one-time-initialization and code running when view is entered, you typically end with controllers looking like this:
// one-time initialization
$scope.updateList = function() {
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
};
$scope.$on('$ionicView.beforeEnter', function () {
$scope.updateList();
});
This should solve your problem without having to trigger events or adding params or data to the route.
Alternative
It is possible to disable view caching in different ways:
cache: false
to the state definitioncache-view="false"
to the html <ion-view ...>
$ionicConfigProvider.views.maxCache(0);
(wouldn't recommend this)Pitfall when using Sub-States
Not in your case, but if editing/creating rows in Sub-States (e.g. states todo
for the list and todo.create
for creating a new todo), there is an additional problem coming from ui-router:
When navigating from todo.create
to state todo
, your super-state todo
won't be "executed", because you're already in this state when coming from todo.create
. This is a common problem and can be solved by one of the more complicated solutions provided in other answers to this post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With