How do navigate to a different state views in an ion-nav-view tab?


#1

Hi,

I have a tabs based application where one of the tabs needs to change its content when the user provides some input.

The basic idea is that the user enters the tab-type view, clicks a button and transitions to the tab-lookup view in the same tab. I thought that I could use multiple views in the same state to accomplish this.

Here is the state configuration.

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('tab.typeit', {
      url: '/type',
      views: {
       'tab-type': {
          templateUrl: 'templates/tab-type.html',
          controller: 'TypeCtrl'
       },
      'tab-lookup': {
          templateUrl: 'templates/tab-lookup.html',
          controller: 'LookupCtrl'
       }         
    }
  })
});

Then in my TypeCtrl controller I have this.

app.controller('TypeCtrl', function($scope, $state, $location, $log) {
    $scope.lookup = false;
    $scope.doit = function() {
        // Called by the form on submit.
        if ($scope.lookup) {
          $state.transitionTo('tab-lookup@tab.typeit');  // <=== THIS FAILS! Syntax is probably wrong.
        }
    };
})

My LookupCtrl controller is very simple:

app.controller('LookupCtrl', function($scope, $log) {
    $log.info('LookupCtrl');
})

But it isn’t working.

Is this the correct paradigm? If not, what is the proper way to do this? If so, what am I doing wrong?

I have read the angular routing documentation but it didn’t help. I am even guess about the @ syntax because I saw it in a post but have not read it in the official documentation.

Any help would be greatly appreciated.

Thanks.


#2

you can use multiple views in the same state, just hide and show the views… no need for a separate route


#3

Thank you for the suggestion but using ng-show negates the need for separate views right? I know that I can do that but I was trying to find a solution based on the angular routing infrastructure so that I could use $state.transitionTo() or $state.go().

I managed to solve the problem using a a nested state that was not part of the abstract tab state.


#4

do you mind sharing your final solution?


#5

I am happy to share it. You folks have done a great job and really appreciate all the help you have given me.

I will post it here later today.


#6

Sorry this is a bit late but here is the basic idea of how to transition to a different view using the angularjs built in $state.transitionTo() and $state.go() capabilities. I hope that you find it helpful.

This example shows an app with two views (and tabs): tab1 and tab2 with a navbar at the bottom of the page. Both views show up in the navbar. When some condition occurs on either page, they transition to the “external” view which is not part of the tab infrastructure and does not have a nav item in the navbar.

The example provided here is not complete because it would be too long. I am only showing the relevant excerpts from the routing (in the app.js file), the controllers (in the controllers.js file) and one example of how you have to duplicate the navbar in the external view (you could, of course, use ng-include).

app.js

In my app.js file I setup the routes for two tabs (tab1 and tab2) as shown below. I also created a completely separate state that is not part of the tabs tree called “external”.

angular.module('starter', ['ionic',
                                         'starter.controllers', 
                                         'starter.services'])

.run(function($ionicPlatform) {
    $ionicPlatform.ready(function() {
      // TODO:
    });
})

.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider

  // setup an abstract state for the tabs directive
  .state('tab', {
    url: "/tab",
    abstract: true,
    templateUrl: "templates/tabs.html"
  })

  // Each tab has its own nav history stack:
  .state('tab.tab1', {
    url: '/tab1',
    views: {
        'tab-tab1': {
            templateUrl: 'templates/tab-tab1.html',
            controller: 'Tab1Ctrl'
        }
    }
  })

  .state('tab.tab2', {
    url: '/tab2',
    views: {
        'tab-tab2': {
            templateUrl: 'templates/tab-tab2.html',
            controller: 'Tab2Ctrl'
        }
    }
  })

  // This state is not part of the tab tree.
  .state('external', {
    url: '/external',
    templateUrl: 'templates/external.html',
    controller: 'ExternalCtrl'
  })

  // if none of the above states are matched, use this as the fallback
  $urlRouterProvider.otherwise('/tab/tab1');

});

controllers.js

In my controllers.js file I can now use transitionTo() or go() to transition to the new state (“external”).

angular.module('starter.controllers', [])

.controller('Tab1Ctrl', function($scope, $state, appServices) {
  $scope.badData = function(bad) {
    // function called when bad data is found.
   appServices.setBadContext('tab1');
   appServices.setBadData(bad);
   $state.transitionTo('external');  // transition here
  };
})

.controller('Tab2Ctrl', function($scope, $state, appServices) {
  $scope.badData = function(bad) {
    // function called when bad data is found.
   appServices.setBadContext('tab2');
   appServices.setBadData(bad);
   $state.transitionTo('external');
  };
})

.controller('ExternalCtrl', function($scope, $state, appServices) {
  $scope.badData = appServices.getBadData();
  $scope.badContext = appServices.getBadContext();
  $scope.goBack = function() {
    $state.transitionTo('tab.' + $scope.badData);
  };
})

templates/external.html

The templates/external.html file cannot use the same setup as the tabs because they do not have direct access to tabs.html which means that the navbar (if there is one, has to be duplicated). There may be a way to workaround that but I didn’t take the time to investigate it.

Here is an example.

<ion-view title="External Views">
    <ion-content class="has-header has-footer padding">
        <h1>External</h1>
        <div ng-bind-html="badData"></div>
        <div ng-bind-html="badContext"></div>
    </ion-content>

    <!-- duplicate the tab nav bar -->
    <div class="tabs tabs-icon-top">

        <a class="tab-item" href="#/tab/tab1">
            <i class="icon ion-home"></i>
            Tab1
        </a>

        <a class="tab-item" href="#/tab/tab2">
            <i class="icon ion-ios7-information"></i>
            Tab2
        </a>

    </div>
</ion-view>