8

I have this state structure:

.state('places',
{
    url:'/places',
    controller:'PlacesController',
    templateUrl:'views/places.html'
})
.state('places.city',
{
    url:'/:city',
    templateUrl:function(stateParams)
    {
        return 'views/places/'+stateParams.city+'.html';
    }
});

It works nicely except when the URL is simply /places without a city after it.
How can I have a default value for templateUrl in the child state?

I'm thinking the best way would be to set the ui-view from PlacesController, however that doesn't seem to be possible.

Francisc
  • 77,430
  • 63
  • 180
  • 276

5 Answers5

15

Try defining another child state with the URL set to an empty string:

.state('places.default', {
    url: '',
    templateUrl: '...'
}

Then add abstract: true to the parent state.

Aaron Torgerson
  • 992
  • 1
  • 7
  • 12
7

Without needing any change in your states configuration, you can put your default template directly between the ui-view tags in your HTML:

<!-- places.html -->
<div ui-view>
  <h1>Please choose a place</h1>
</div>

<!-- london.html -->
<h1>London is amazing!</h1>

Now when you navigate to /places, you will see the "Please choose a place" message, and when you navigate to /places/london, you will see "London is amazing!".

Elise
  • 5,086
  • 4
  • 36
  • 51
1

as stated by Aaron you can use $state to navigate to a default child state but here there is a catch say suppose you have more than 1 child :

    .state('places',
    {
        url:'/places',
        controller:'PlacesController',
        templateUrl:'views/places.html'
    })
    .state('places.city',
    {
        url:'/:city',
        templateUrl:function(stateParams)
        {
            return 'views/places/'+stateParams.city+'.html';
        }
    })  
    .state('places.child2',
    {
        url:'/:city2',
        templateUrl:function(stateParams)
        {
            return 'views/places/'+stateParams.child2+'.html';
        }
    });

and in you parent controller PlacesController you have $state.go(places.city) then whenever the parent controller i.e. PlacesController is invoked you will be redirected to city state. So if someone is on child2 state and presses a refresh button then parent controller will be invoked and he will be redirected to city which is not what you want!

ANS: So you can check for the current state before doing a redirection i.e. if the person is in parent state then redirect to any default child state but if the person is in any of the child states then do not do the redirection in the parent controller :-

 if($state.current.name == "places"){
     $state.go('places.city');
 }

hope this helps!

Rishul Matta
  • 3,383
  • 5
  • 23
  • 29
1

Use resolve on the parent state

.state('places',
{
    url:'/places',
    resolve: { default: function($state) {
      if ($state.is('places')) $state.go('places.city', { url: 'london'})
    }}
    controller:'PlacesController',
    templateUrl:'views/places.html'
})
.state('places.city',
{
    url:'/:city',
    templateUrl:function(stateParams)
    {
        return 'views/places/'+stateParams.city+'.html';
    }
});

Check for syntax error, I'm used to coffeescript :)

Shining Love Star
  • 5,734
  • 5
  • 39
  • 49
0

As stated in the Angular-UI Wiki page:

There are three main ways to activate a state:

  1. Call $state.go(). High-level convenience method.
  2. Click a link containing the ui-sref directive.
  3. Navigate to the url associated with the state.

https://github.com/angular-ui/ui-router/wiki#activating-a-state

Francisc
  • 77,430
  • 63
  • 180
  • 276
  • 7
    This answer shouldn't be accepted. It doesn't answer the question, which is about defaulting to a child state when a parent state is invoked. – XML Oct 03 '14 at 06:31
  • 1
    +1 for the answer, I had the same question as the OP and it would seem invoking a child from a parent is not the right thinking, simply accessing the child route has the same effect with no thinking involved. – HappyCoder Feb 20 '15 at 21:26
  • this is not a solution for delegating a state by it's child! – Adnane.T Nov 16 '15 at 19:43