Reload and display new data in ng-repeat when clicking back button

Background

I have an ng-repeat list that goes to a details page (which has a back button). The $scope.items variable is loaded from a get request that occurs when the page is first loaded, with my refreshItems() function.

The Problem

When you click the back button on the details page, you are taken back to the correct page, but the list is not refreshed. I need this list to refresh so the new items are loaded and shown.

Attempted Solution

I thought that I could simply hook up the Back button to an ng-click function that uses ionicHistory to go back, and then calls my refreshItems() function; however, this does not reload the items on the first page.

The above attempt does go back to the last page and trigger the refreshItems() function (and the new data is loaded, which I can see thanks to console.log() statements), but I’m guessing the ng-repeat needs to be rebuilt. I found some information on $scope.$apply() as well as $route.reload() but neither of these fixed the problem when I placed them at the end of my goBack() function.

Code Excerpts

controller.js

$scope.refreshItems = function() {

	console.log("Refreshing items!");

	$http.get('http://domain/page.aspx').then(function(resp) {
		$scope.items = resp.data; console.log('[Items] Success', resp.data);
	}, function(err) { console.error('ERR', err); });
	
};


$scope.goBack = function() {
	$ionicHistory.goBack();
	$scope.refreshItems();
};

Main Page HTML

<div class="list">
	
	<a ng-repeat="i in items" class="item" href="#/tab/details?ID={{i.Item_ID}}">
		<b>Item {{i.Item_Name}}</b>
	</a>
	
</div>

Back Button on Details Page

<ion-nav-bar>
	<ion-nav-back-button class="button-clear" ng-click="goBack();">
		<i class="ion-arrow-left-c"></i> Back
	</ion-nav-back-button>
</ion-nav-bar>

Possible Direction?

I have a refresher on the main page which calls refreshItems() - and it refreshes them correctly. The problem is most certainly when I try to pair refreshing with either $ionicHistory.goBack() or $state.go(). Is there a way I can programmatically call the refresher (after/on load), since directly calling the function that refresher is calling is not working?

2 Likes

I am having the exact same issue here. :weary:

I’m having a similar issue. I have an app that progresses the user through several views and at the last view a button to send the user back to the beginning to start over. The start over button uses $location.Path(’/’) to take the user back to the beginning but the controllers are not reinitialized and so the model is not refreshed

If I have understood you correctly, I think some of your issue is being caused by the caching of views and the other by not getting the DOM to refresh. One possible solution would be to listne for the ‘$ionicView.enter’ event on your list controller and then call the refreshItems function then.

If you want to be slightly more clever you could use $ionicHistory and it’s backView() function to check that you were coming from the details page and then refreshItems… or similar.

To get the list to refresh, I usually just use $timeout i.e. in your code
$scope.items = resp.data; would become…
$timeout(function(){
$scope.items = resp.data;
},0);

HTH

I figured out a solution for this!

The solution is to use the $scope.$on('$stateChangeSuccess') function. Either check the to/from view with function parameters, or use $location.path():

$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {

	console.log("State changed: ", toState);
	
	if ($location.path() == "/tab/main") {
		$scope.refreshItems();
    }

}

@MWright24 the resolve is an interesting idea that may also work.

1 Like

EFA :smile:

Also doing the refreshMachines(); on state change, the page state is still going to change and you’d still be presented a page with no data, and putting a timeout there isn’t a dynamic fix as there could be more data than what your first timeout was for. Other phones/devices could render the data quicker than other phone so a timeout isn’t necessary for the length you declared.

@MWright24, just wondering if you could explain what the app user actually experiences with your resolve solution. I remember playing around with resolve some time ago but if I remember, if you are asynchronously loading a lot of data in it, ionic/angular will not navigate to the new view until it has been resolved. Therefore the user gets stuck on the old view not knowing what is going on… how did you handle this? I could have that completely wrong… so sorry. That’s why I chose back then not to use resolve and simply navigate to the new view and then load the data (showing a loading icon if necessary).

For my learning do you mind also explaining what you mean by …putting a timeout there isn’t a dynamic fix as there could be more data than what your first timeout was for?

Thanks

The user will see a slight delay but only a delay as long as it takes to resolve the data, putting a timeout on a function is a hot fix. Lets say your timeout is currently for 30 machines and it works perfectly on your device, 30 machines on another device may take longer to process therefore the timeout doesn’t function as you want it. This will also happen when you have more machines than you anticipated for the timeout.

The user won’t get stuck, the user is only navigated to the intended state once the function has been resolved, the resolve will be quicker than your timeout as it’s synchronously calling the functions and when ready the state change will happen. Whereas will a timeout your asynchronously calling the functions and relying on a timeout to be the correct amount of time.

You can use cache-view to keep the scope for that state in cache, this’ll only work if the data on the page is the same. e.g. you have an option of a or b on page 1 this takes you to page 2 with a’s data or with b’s data - this is when you can’t use cache view.

Hope that explains things, the above was my solution to an easier maintained app. Your solution might not be the same as mine but it’s good to offer alternatives.

Mat.

Ihave the same problem as the OP: when I get to back to the list page using $ionicHistory.goBack() I call the RefreshData function on the controller and it does get the new data (verified with console.log) but it does not refresh the list in the UI (ng-repeat list). Again, I have an ion-refresher which works fine when I pull to reload.

Now, how do I force the list to be redrawn?

LE: calling refreshList within a $timeout is the solution (as it calls $apply() itself):

$timeout(function() {
                $scope.refreshList();                
            },$rootScope.TIMEOUT_BEFORE_LIST_REFRESH);

But that was not the only solution in my case: I found out that the service was returning the same list due to some database lag between insert and retrieve so the list was updating but with the same data, hence the Timeout param :smile:

I think that is because is being chached.

Try set the cache property to false in your routes:

$stateProvider.state('myState', {
   cache: false,
   url : '/myUrl',
   templateUrl : 'my-template.html'
})

or in your ion-view:

<ion-view cache-view="false" view-title="My Title!">
4 Likes

@bosch I found a solution to my original problem and I posted it above. Reload and display new data in ng-repeat when clicking back button

Better solution. Thanks!!

1 Like

<ion-view cache-view="false">
The smartest solution, thank you Matias

This worked great for me! Thank you so much!

Best Solution… its really best

Thx, For me Work First