Child states do not transition properly


#1

Seems that when you have child states with dot notation, transitioning to them doesn’t work. The controllers do not get initialized either. The URL does change. Example:

.state('receive', {
  url: '/receive',
  templateUrl: 'templates/receive.html',
  controller: 'ReceiveCtrl',
  resolve: {
    purchaseOrders: function() {
         ....
    }
  }
})

.state('receive.purchaseOrder', {
  url: '/:purchaseOrderId',
  controller: 'ReceiveItemsCtrl',
  templateUrl: 'templates/receive-item.html',
  resolve: {
    purchaseOrder: function() {
       ...
    }
  }
});

If I create a separate state for “receive.purchaseOrder”, it works. Do I need to structure my child states differently? I’ve used this ui-router convention in other projects outside of Ionic and it seems to work.

I’ve tried all different ways of switching states and none seem to work.

  $scope.goToPurchaseOrder = function(purchaseOrderId) {
    $state.go('receive.purchaseOrder', { purchaseOrderId: purchaseOrderId});
  };

  <ion-item ng-repeat="purchaseOrder in purchaseOrders" item="purchaseOrder"
    ng-click="goToPurchaseOrder(purchaseOrder.po_id)">
   <strong>{{ purchaseOrder.po_id }}</strong>
  </ion-item>

#2

It’ll be a lot easier for us to help if you post a code pen sample. Just looking at your code, I don’t see anything that jumps out as wrong.

I would wonder about the receive.purchaseOrder state. That URL is pretty ambiguous. I’m not sure if UI router can handle that or not as so many routes might look like that. Perhaps try changing it to :

.state('receive.purchaseOrder', {
  url: '/order/:purchaseOrderId',
  controller: 'ReceiveItemsCtrl',
  templateUrl: 'templates/receive-item.html',
  resolve: {
    purchaseOrder: function() {
       ...
    }
  }
});

#3

Yeah, I’ll put a pen together. The URL shouldn’t matter, because child states will always append their URL to the parent (via UI-Router docs, and other apps that I’ve built. :smile:)


#4

This still seems to be an issue for me. The states are definitely valid, otherwise ui-router would be throwing errors. The URL changes in the browser, but no transition happens.

Like I said, I’m using this convention outside of this Ionic project (separate one now) and it works. Not sure what’s up!

EDIT:

Seems that if you used named views and explicitly override the parent’s template using the @ notation.

    views: {
        'main@': {
            controller: 'ReceiveController',
            templateUrl: 'main/receive/receive.tpl.html'
        }
    }

#5

It seems to work using the @ notation BUT you need to override the correct state.

So if you are using the starter project

  .state('tab', {
    abstract: true,
    templateUrl: 'templates/tabs.html'

In your tabs.html you have the placeholders for the children states:

<!-- Dashboard Tab -->
<ion-tab title="Dashboard" icon="icon ion-home" ui-sref="tab.dash">
  <ion-nav-view name="tab-dash"></ion-nav-view>
</ion-tab>

And you have your child state

  .state('tab.dash', {
    url: '/dash',
    views: {
      'tab-dash': {
        templateUrl: 'templates/tab-dash.html',

As expected the content of tab-dash.html fill the placeholder of the parent state (tab): <ion-nav-view name="tab-dash"></ion-nav-view>

Now you want to add a child to the state and you expect to fill the same/previous placeholder.

Well you can define your state as follow:

  .state('tab.dash.detail', {
    url: '/:subjectId',
    views: {
      'tab-dash@tab': {
        templateUrl: 'templates/dash-detail.html',

This reads:

Hey ui-router, please fill the placeholder (<ion-nav-view name="tab-dash"></ion-nav-view>) of my grand parent state (tab-dash@tab) with the content of my amazing template dash-detail.html.

So the trick is to target the correct views (tab-dash) in the correct state (tab).


#6

How would you do this?

2 tabs:

  • list
  • map

both with elements that navigate to a common detail page.