Steve
Steve

Reputation: 14912

Angular UI-router, nested states don't show

I have a UI-Router document set up to show the "pages" sections of a demo.

(function() {

  'use strict';
  angular.module('pb.ds.pages').config(function($stateProvider) {
    $stateProvider.state('pages', {
        abstract: true,
        url: '/pages',
        templateUrl: 'modules/pages/templates/pages.html',
        controller: 'PagesController as pages',
        data: {
          pageTitle: 'Pages',
          access: 'public',
          bodyClass: 'pages'
        }
      })
      .state('pages.signin', {
        url: '/signin',
        templateURL: 'modules/pages/templates/signin.html',
        controller: 'SignInController as signin'
      })
      .state('pages.forgotpassword', {
        url: '/forgotpassword',
        templateURL: 'modules/pages/templates/forgotpassword.html',
        controller: 'ForgotPasswordController as forgot'
      })
      .state('pages.404', {
        url: '/404',
        templateURL: 'modules/pages/templates/404.html',
        controller: '404Controller'
      });
  });

})();

The parent state, "pages" has the ui-view on it, but otherwise I don't need to "show" it. I am only interested in showing its children, such as pages.signin or pages.forgotpassword.

Typing in the url "/forgotpassword" bounces me back to my homepage, which is the "otherwise" state in my app.module.js

// UI ROUTER CONFIG
angular.module('app').config(function($stateProvider) {
    $stateProvider.state('otherwise', {
      url: '*path',
      template: '',
      controller: function($state) {
        $state.go('dashboard');
      }
    });
});

No errors in console, and all the pages in question are linked in my index.html.

I'm sure I must have missed something obvious. Any clues?

UPDATE

If I enter /pages/forgotpassword it does go to the correct path but the view is not being populated by the template...

Upvotes: 2

Views: 630

Answers (2)

Radim Köhler
Radim Köhler

Reputation: 123861

There is a working plunker

We have to adjust state definition like this:

 $stateProvider.state('pages', {
    abstract: true,
    //url: '/pages',
    templateUrl: 'modules/pages/templates/pages.html',
    controller: 'PagesController as pages',
    data: {
      pageTitle: 'Pages',
      access: 'public',
      bodyClass: 'pages'
    }
  })
  .state('pages.signin', {
    url: '/signin',
    // templateURL: 'modules/pages/templates/signin.html',
    templateUrl: 'modules/pages/templates/signin.html',
    controller: 'SignInController as signin'
  })
  .state('pages.forgotpassword', {
    url: '/forgotpassword',
    //templateURL: 'modules/pages/templates/forgotpassword.html',
    templateUrl: 'modules/pages/templates/forgotpassword.html',
    controller: 'ForgotPasswordController as forgot'
  })

The most important is replacement of the templateURL with templateUrl. Javascript (and UI-Router) is case sensitive.

We also do not need define url for parent... it could be just child state definition

Finally, we must be sure, that our parent contains some target ui-view="" where child states will be placed. E.g. this is the plunker pages.html:

<div>
  <h3>pages</h3>      
  <hr />       
  <div ui-view=""></div>      
</div>

These links will then work as expected:

//href
<a href="#/signin">
<a href="#/forgotpassword">
//ui-sref
<a ui-sref="pages.signin">
<a ui-sref="pages.forgotpassword">

We can leave the parent url:

 $stateProvider.state('pages', {
    abstract: true,
    url: '/pages',
    ...

but the href links for child states must contain the parent url as well:

<a href="#/pages/signin">
<a href="#/pages/forgotpassword">

Check it here in action

Upvotes: 1

manzapanza
manzapanza

Reputation: 6205

You need to prefix the state url with the url of the parent state. So the correct url that you need open with the browser should be: #/pages/forgotpassword

Check the doc URL Routing for Nested States

Upvotes: 0

Related Questions