Issues w/ routing / $state.go


#1

Hey there,
I’ve an issue w/ $state.go() to change views.

I’ve implemented a login-system which broadcasts an “AuthEvent” once the user is logged in (or if there’s a login-token available).
Unfortunately, my $state.go()-directives don’t do anything expect for changing the URL (i.e. index.html#/ --> index.html#/login) - but not the view on the screen! If I reload the page after the URL-change, everything is displayed correctly.

My routing:

    .config(function($stateProvider, $urlRouterProvider) {
    $stateProvider.state('login', {
        url: '/login',
        views: {
            'login': {
                templateUrl: 'templates/login.html'
            }
        },
        controller: 'introCtrl'
    });
    $stateProvider.state('main', {
        url: '/',
        views: {
            'main': {
                templateUrl: 'templates/main.html'
            }
        },
        controller: 'mainCtrl'
    });

The routung-calls look like this:

$state.go('login');

Thanks in advance!


#2

When you catch the event, try wrapping the $state.go('login') in a $timeout. Also, if you are already on the login state/url then you will have to explicitly refresh. Do you have multiple directives trying to change the ui-state at once?


#3

Thanks for your reply! I tried wrapping my $state.go()-call in a $timeout, as suggested, even though I’m not sure what the purpose of that would be…?

function() {
  console.log('DEBUG: $state.go');
  $state.go('login');
},2000

This now takes 2s to change the URL (as expected), but the view doesn’t load anyways (at least until I refresh the page of course).
I’ve also added a debug-log in front of every $state.go()-directive to find out if there are multiple calls occurring at once, but apparently, there’s only the one now wrapped inside the timeout.

Second question, hope it’s okay to put this in this thread as well: Is there any method to automatically fire a function ($http-event in my case) when a specific view is rendered? e.g., after the login, fetch data from the server and populate the page.


#4

The purpose of the $timeout is to add your ‘action’ to the end of the digest cycle. It’s an AngularJS thing. You don’t need to add a delay though, you would want to do something like this probably:

$timeout(function() {
  console.log('DEBUG: $state.go');
  $state.go('login');
});

To answer your second question, look at the events on the very bottom of this page: https://github.com/angular-ui/ui-router/wiki

ionic uses ui-router underneath so these events will be fired accordingly.


#5

@arthoc did you manage to get this working please? I have

 .controller('PlayCtrl', function ($scope) {
    $scope.home = function () {
        $state.go('home');
    };
});

Which like you changes the url (when using ionic serve) but doesn’t update the view. I have tried

      $scope.home = function () {
            $timeout(function () {
            $state.go('home');
        });
    };

All I’m trying to do is get a to change state for me

<button class="button icon ion-arrow-return-left actionButton" ng-click="home()"></button>

Thank you


#6

@Russ_T can you copy-paste your html templates here?

I had a similar issue with changing routes/states, but it turned out to be html templates being incompatible with the Ionic version that i was using.

               <ion-side-menu side="left" width="200">
                    <header class="bar bar-header bar-stable">
                        <h1 class="title">Left</h1>
                    </header>
                    <ion-content class="has-header">
                        <ion-list>
                            <ion-item nav-clear menu-close href="#/event/check-in">
                                Check-in
                            </ion-item>
                            <ion-item nav-clear menu-close href="#/event/attendees">
                                Attendees
                            </ion-item>
                        </ion-list>
                    </ion-content>
                </ion-side-menu>

But after changing it to the following, routes worked fine.

               <ion-side-menu side="left" width="200">
                    <!-- changed header to ion-header-bar -->
                    <ion-header-bar class="bar bar-header bar-stable">
                        <h1 class="title">Left</h1>
                    </ion-header-bar>
                    <ion-content>
                        <!-- replaced ion-list and ion-item below -->
                        <ul class="list">
                            <a class="item" menu-close href="#/event/check-in">
                                Check-in
                            </a>
                            <a class="item" menu-close href="#/event/attendees">
                                Attendees
                            </a>
                        </ul>
                    </ion-content>
                </ion-side-menu>

It could be something related to your html templates/partials too. Check it out…


#7

Instead of href u could do ui-sref


#8

Hi @sreekanth, thanks for your help.

I have tried to change my templates to match yours, but it hasn’t changed anything. I have changed around a default tab project, on one of the tabs I would like to go to an entirely different state outside of the tabs.

Index.html

    <ion-nav-bar align-title="left">
    <ion-nav-back-button></ion-nav-back-button>
</ion-nav-bar>

<ion-nav-view name="index" class="paddedBottom">
</ion-nav-view>

tabs.html

<ion-view title="tabs" view-title="My app name">
<ion-nav-title>
    <img src="img/logo.png" height="40px">
    My app name
</ion-nav-title>
</ion-view>

<ion-tabs class="tabs-striped tabs-color-light">   
<ion-tab title="tab1" icon-off="ion-ios-moon-outline" icon-on="ion-ios7-moon" ui-sref="home.tab1">
    <ion-nav-view name="tab-experience"></ion-nav-view>
</ion-tab>
<ion-tab title="tab2" icon-off="ion-ios7-play-outline" icon-on="ion-ios7-play" ui-sref="home.tab2">
    <ion-nav-view name="tab-play"></ion-nav-view>
</ion-tab>
</ion-tabs>

tab2.html

<div></div>
<ion-content>
<ul class="list">
    <a class="item item-avatar item-icon-right" ng-repeat="bla in blas | orderBy : 'favourite' : true" type="item-text-wrap" href="#/tab/settings/{{experience.id}}">
        <img ng-src="{{bla.icon}}">
        <h2>{{bla.name}}</h2>
    </a>
</ul>
</ion-content>

<button class="button icon ion-play actionButton" ng-click="newState()"></button>

newState.html

<div class="fade2black"></div>

<button class="button icon ion-arrow-return-left actionButton" ng-click="backToTabs()"></button>

I’m not sure that’ll shed any light, but it’s most odd. My backToTabs() and newState() are being called ok as I’ve also put an alert in with them.

Thanks again :smile:


#9

@Russ_T Could you use plnkr.co and paste your entire code there? I could debug there…


#10

@sreekanth, thank you for your help.

I have added it to http://plnkr.co/edit/uKNzS0UJOhYw2fjpRZVy?p=preview, but I cannot at the moment get it to work. I will keep fiddling until I have figured plunker out though :smile:


#11

@Russ_T There were some typos and missing imgs… I have commented out missing img tags and fixed the typos … check this out… http://plnkr.co/edit/QOhlTRSxsHNW640uKkKU?p=preview


#12

It works! Hoorah!! This will teach me to code at 4am, but I couldn’t help myself I was getting so close to getting it working.

Thank you very much for your help, I’ll go off and digest what I did wrong :blush:


#13

Experiencing lazy-loading/Cache issue in "version": "1.0.0-beta.14",
Where the controller is not being instantiated, when an state is being invoked from another controller like:

 $state.go('tab.home');

$state.go() worked fine & controller instantiated successfully in this "version": "1.0.0-beta.8",

$state is being injected into controller fine.
tried below combinations (Sometimes with event.preventDefault();), but to no avail.

$state.go('tab.home', {reload: true});

$state.transientTo('tab.home');

#14

The issue I was facing above is due to the cached views introduced in “version”: “1.0.0-beta.14”,. At this time, I was able to resolve it by disabling cache for all views through config provider.

$ionicConfigProvider.views.maxCache(0);

It would be neat to have this option available/controllable for a view than for the entire app, something like:

$state.go('tab.home',{}, {reload:true});

#15

@acveer You could disable cache per view/state too (as shown below)… For more details, http://ionicframework.com/docs/api/directive/ionNavView/

Disable cache within state provider

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

Disable cache with an attribute

<ion-view cache-view="false" view-title="My Title!">
  ...
</ion-view>

#16

Thank you @sreekanth. Both solutions work great.


#17

Does anyone think this is promotable to a bug? The fact that disabling the cache fixes this “simply navigation” workflow makes me think what are the real usages of cache system and what are the risks of it.

Regards


#18

Have you find a solution? $state.go still doesn’t work even though I have disable the cache


#19

Using an empty $timeout fixed an issue I was having (on iOS), where the $state.go(state) call would sometimes ‘go’ to the very same view. Will keep DOM rendering behaviour in mind in future - thanks!