Please help test: Angular 1.3, improved transitions, cached views, etc

@Mik378 : You asked why some console statements did not show up. I’m assuming that in your controller for A, you have some logging like console.log('Controller A loaded!'). Then, you navigate to B and back to A. You are expecting the logging statements from Controller A to fire again, right?

If so, they will never do this. The controller never left memory; so, it does not reload again. This is VERY different than the way Ionic used to work. In the past, when you navigate from a view, that controller is destroyed. With Caching, the controller is disconnected and then reconnected when the view comes back.

So, if you need to do stuff when the controller is reconnected, you need to do use the new $ionicView.x events.

Example:

angular.modue('myApp').controller('ControllerA', function($scope) {

        $scope.$on('$ionicView.enter', function() {
           console.log('Controller A loaded!');
           // do stuff here like update your model
        });

});

There are other $ionicView events documented here : http://ionicframework.com/docs/nightly/api/directive/ionView/

2 Likes

Adam,

Did you get a chance to look at : Please help test: Angular 1.3, improved transitions, cached views, etc

With all the new $ionicView.X events, we really don’t need these ui-router state events. However, it might be a good idea to document this in the ionicView documents. People are really used to these events.

1 Like

Great :slight_smile: Thanks

Just another question:

I want to refresh the cached view when I load it through a tab-item?
Is there a way to do it? Indeed, I want for example to force refresh of the whole A’s list, when clicking on my tab “View A” .
But I still need to cache it when back from B.

$ionicSlideBoxDelegate.{next(),previous()} don’t work. Tried with $getByHandle too, nothing changes.

$ionicSlideBoxDelegate.{next(),previous()} now return the next/previous index. Use $ionicSlideBoxDelegate.select($ionicSlideBoxDelegate.previous()). http://code.ionicframework.com/nightly/CHANGELOG.jtml

I brought my slideBox to be almost identical to the one at codepen¹, and it still doesn’t work (doesn’t slide with touch events, and nor does it work through the delegate). I was able to make it ‘work’ once using a ion-content with scroll=“true” but performance was bad for some reason and it messes up some of my styling. [1] {simple ion-view inside a global ion-nav-view}, {no ion-content nor ion-scroll}, {no custom CSS that affects positioning or behaviour, only presentation}.

Could you post a codepen of what you’re doing?

Your slidebox now needs a parent that defines width/height explicitly (ion-content works perfectly for this). I’m still looking at ways to solve this.

Tabs have an on-select event. So, you can use that to force a reload.

Docs : http://ionicframework.com/docs/nightly/api/directive/ionTab/

@adam I’m not sure that I could replicate it with a codepen. There is a thread on it, on here. I can diagram what is happening though.

----------------------------1
---------------2-----------3-----------4
-----------5–6--7-----8–9

Those are the stacks I’m using to navigate. 1 is an abstract parent, as are 2 and 3. States 4 -9 actually show the content. If I am in states 5 or 6 and attempt to go to state 4 I can see the code going to state 4, then it calls state 7, and finally makes a call to whatever state I am attempting to navigate away from. The same thing happens if I am in state 8 going to state 4. It calls 4, then 9, then back to 8. Interestingly if I am in 7 or 9 the state changes to 4 with no issue. I wll update this post with the link to the other thread momentarily. Here is the link: Linking to states in tabs

Yes, but how to avoid two reloads …if the page was not already cached firstly?

I would imagine this pseudo-code: on-select=“myState.reload()”.
If the targeted view was not already cached, may it end up to load the view twice?

Or is there a better way to force a reload ?

The on-select event doesn’t do anything with the view. it just gives you an opportunity to run some method on your controller. So, it won’t cause the view to load twice.

So, your controller might look like this:

angular.module('Tab1Controller', function($scope,DataService) {
    
  $scope.customers = [];
  
  // Will load the customers the first time the controller is loaded
  loadCustomers();

  // Use with the on-select event to load refresh data
  $scope.reloadCustomers = function() {
    loadCustomers();
  }

  function loadCustomers() {
    DataService.load('xyz').then(
      function(results) {
       $scope.customers = results;
      }
    )
  }
});

Let’s suppose two tabs Tab0 and Tab1.
At startup, Tab0 is displayed.
When I click on Tab1, your Tab1Controller is executed, loading customers.
But also the on-select event, triggering reloadCustomers ! , loading twice the customers…

Am I wrong?

So then just do this :

angular.module('Tab1Controller', function($scope,DataService) {
    
  $scope.customers = [];
  
  // Use with the on-select event to load refresh data
  $scope.reloadCustomers = function() {
    loadCustomers();
  }

  function loadCustomers() {
    DataService.load('xyz').then(
      function(results) {
       $scope.customers = results;
      }
    )
  }
});

Now, no customers will be loaded until the tab is selected (either by default as the tab view loads or the user chooses that tab).

1 Like

Here is a Plunker with some parts of my app that shows the $ionicSlideBoxDelegate.select() issue.
The slide with index 0 is always shown in the modal. This feature works in b13 using the .slide() method.

But you suppose that Tab1Controller is the direct controller that would do the reload.
Actually, I made a TabsCtrl merely managing some “tabs mechanism”. (state called ‘tabs’ with abstract:true)
And a lot of nested states like tabs.customers, tabs.notifications etc. , corresponding to each particular controller making the logic.
To sum up, TabsCtrl has no knowledge at all about the way to reload a customers.
It’s defined in the corresponding child controller: CustomersCtrl associated to the nested state: tabs.customers.

I don’t find a way to use the on-select directive to target child controllers (nested states), making the needed reloads.

=> I’m still stuck with cached views.
I only need them for the “back” navigation, not the click on tabs supposing to refresh (more UX-oriented).

I’ve come across a somewhat strange issue. I have a directive for wrapping my pages in the appropriate ion-view / ion-content tags. After updating to nightly 782 the title no longer gets set in the header. My template looks like this:

<ion-view view-title="{{viewTitle}}"><ion-content class="has-header padding"><div ng-transclude></div></ion-content></ion-view>

Even when I set the title to plain text it isn’t set. Moving this exact same code into the individual pages works fine. Any thoughts?

@xephorus Can you provide a codepen? Why can you not use just the ion-view directive instead of creating your own?

@JesperWe Thank you for putting together the plunker! It helped me narrow down what the issue was, so the fix is in build 793. Please let me know if you have any other issues and thanks for creating the example and describing the problem.

@jrowny To follow up on your question about using ion-header-bar in an ion-view, is there any reason you needed to use ion-header-bar with the bar-subheader css class over just using a div? Like this:

    <div class="bar bar-subheader">
      <div>My subheader</div>
    </div>

Reason I ask is because we might go back to having ion-header-bar trump the ion-nav-bar when a header bar is supplied in the ion-view. We need a directive that can override the nav-bar with custom header content, and that’s what ion-header-bar is supposed to do. So I just wanted to check with you first to see if there was something I’m missing before adding that code back in. Thanks

@Calendee Great find! There was a point in the code that the entering and leaving scopes were both connected, and at that time was when the $broadcast was fired, so both scopes listened to the event.

I changed it so that the leaving scope gets disconnected BEFORE the entering scope gets reconnected or a new scope is created for the entering view. Thanks for the detailed description of the problem with codepens!

When I switch tabs it does not work. But $ionicView.enter works well

.controller(‘MainCtrl’,function($scope,$rootScope,$ionicPlatform,EventService,$window){
$rootScope.$on(’$ionicView.leave’,function(){
//$rootScope.loadingView = true;
console.log(111);
});
$rootScope.$on(’$ionicView.enter’,function(){
console.log(122);
$rootScope.loadingView = false;
});

});

l have seen https://github.com/driftyco/ionic/commit/fb81f9704f3de56b0a49ed43fefa650d42b2263c and download the lastest version.But it also dont work.

Issues with collection-repeat lists in tabs, possibly caused by cached views.

My app has collection-repeat lists in seperate tab views, when fast switching between tabs, occasionally the list views will not refresh correctly, resulting in only one item left in the list view, all other items gone and unable to refresh the list view.

It’s also possible to always show the problem with the following steps:

  1. Switch to one tab with list views
  2. And then rotate the phone orientation to redraw the list view.
  3. Switch to another tab with list views, now the list views refresh but only one item left (seems to be last item in the list).

Lastest nightly 792 with iOS6 and iOS7, using Sarfari/Chrome browsers and PhoneGap developer.

Dunno if this has already been addressed, or is just a dumb question, but:
if ScrollBox now needs a parent with a defined height, does this makes impossible creating a fullscreen slidebox with infinite scroll lists in each slide?