Search code examples
javascriptangularjssingle-page-applicationangular-ui-routerstates

How to navigate between parameterized URLs within the same state?


I have a parent state myApp, and a child state planManager. planManager is a view that contains three parameter defined URLs: planManager/a, planManager/b and planManager/c, where a, b and c are the parameter defined in:

.config(function config( $stateProvider, $urlRouterProvider ) {
 $stateProvider.state( 'planManager', {
 url: '/planManager/:state',
 views: {
  "main": {
    controller: 'planManagerControl',
    templateUrl: 'planManager/planManager.tpl.html'
  }
 },
data:{ pageTitle: 'Plan Manager' }
});

Depending on the state parameter 'state', I am displaying and hiding 3 divs in the template.

I can navigate from my parent state to planManager, using

<a href ui-sref="planManagerTest({state: 'a'})">Plan Manager</a>

But I am unable to navigate to

 planManagerTest({state: 'b'}) or planManagerTest({state: 'c'}) 

from planManagerTest({state: 'a'})

I have tried , , .. but I keep getting the error "cant navigate to state / from planManager'

How can I manage to do this navigation?

EDIT: I resolved this .. just got the syntax wrong - I tried

<a  href ui-sref=".({state: 'b'})">

And navigation started working like a charm!


Solution

  • What you are experiencing is (was) most likely issue with:

    The name of the state that will be transitioned to or a relative state path. If the path starts with ^ or . then it is relative, otherwise it is absolute.

    Some examples:

    • $state.go('contact.detail') will go to the 'contact.detail' state
    • $state.go('^') will go to a parent state.
    • $state.go('^.sibling') will go to a sibling state.
    • $state.go('.child.grandchild') will go to a grandchild state.

    Which is almost the same as the way how to use ui-sref. See this comment there:

    A note on relative ui-sref targets:

    You can also use relative state paths within ui-sref, just like the relative paths passed to state.go(). You just need to be aware that the path is relative to the state that the link lives in, in other words the state that loaded the template containing the link.

    To demonstrate that all, there is a plunker:

    Let's say we have parent and child states defined this way:

    $stateProvider.state('myApp', {
        url: '/myApp',
        templateUrl: 'myApp.tpl.html',
      });
      $stateProvider.state('myApp.planManager', {
        url: '/planManager/:state',
        views: {
          "main": {
            controller: 'planManagerControl',
            templateUrl: 'planManager.tpl.html',
          }
        },
        ...
    

    Then inside of the root (index.html) we can/have to use absolute:

    <ul>
      <li><a ui-sref="myApp.planManager({state:'a'})">myApp.planManager({state:'a'})</a></li>
      <li><a ui-sref="myApp.planManager({state:'b'})">myApp.planManager({state:'b'})</a></li>
      <li><a ui-sref="myApp.planManager({state:'c'})">myApp.planManager({state:'c'})</a></li>
    </ul>
    

    This could be the myApp state, profiting from relative path to children:

    <ul>
      <li><a ui-sref=".planManager({state:'a'})">.planManager({state:'a'})</a></li>
      <li><a ui-sref=".planManager({state:'b'})">.planManager({state:'b'})</a></li>
      <li><a ui-sref=".planManager({state:'c'})">.planManager({state:'c'})</a></li>
    </ul>
    

    And the sibling calls from the planManager state

    <ul>
      <li><a ui-sref=".({state:'a'})">.({state:'a'})</a></li>
      <li><a ui-sref=".({state:'b'})">.({state:'b'})</a></li>
      <li><a ui-sref=".({state:'c'})">.({state:'c'})</a></li>
    </ul>
    

    The example is here