Langdon
Langdon

Reputation: 20073

Default nested ui-views in ui-router

I'm having trouble with a simple ui-router sample I have set up. I have a company page, whose default sub-state should show CompanyProfile, but it defaults to nothing until I click profile. Once I clicked employees, I have to click profile twice to get it to show again. Ideally I want ui-sref="company()" and ui-sref="company.profile()" to display the same screens. It seems like I'm missing something small..

Here's the plnkr:

http://plnkr.co/edit/A3LHGqQIuRlK1QdjuzrP?p=preview

HTML:

  <a ui-sref="company()">company</a>
  | <a ui-sref="company.profile()">profile</a>
  | <a ui-sref="company.employees()">employees</a>

JS:

$stateProvider
    .state('company', {
        url: '/',
        templateUrl: 'company.html',
        controller: 'CompanyCtrl as CompanyCtrl'
    })
    .state('company.profile', {
        url: '',
        templateUrl: 'profile.html',
        controller: 'CompanyProfileCtrl as CompanyProfileCtrl'
    })
    .state('company.employees', {
        url: '/employees',
        templateUrl: 'employees.html',
        controller: 'CompanyEmployeesCtrl as CompanyEmployeesCtrl'
    });

btw, I'm writing everything as components and decided to define the routes in each component, so you'll find the 3 state definitions in the 3 controllers. I'm not entirely sure this is the best approach or not yet.

Upvotes: 0

Views: 1243

Answers (1)

ryeballar
ryeballar

Reputation: 30098

The default state is entirely dependent on how you call $urlRouterProvider.otherwise(), passing it a url transitions the application to the particular url, wherein ui-router detects and looks for the very first state it sees.

In your main.js configuration, defines the / url as the default url for the application, which is technically the company state's url and is the very first state in the chain of parent states and children states, making it the default state. This in fact, is also the resulting url for the company.profile state that you wanted your application to default to.

To solve this problem, depends on the use cases for your application.

  1. Use case: If your application defines the company state as a non-navigational state, then setting it to an abstract state solves the problem.

DEMO

CompanyCtrl.js

$stateProvider
    .state('company', {
        abstract: true,
        url: '/',
        templateUrl: 'company.html',
        controller: 'CompanyCtrl as CompanyCtrl'
    });
  1. Use case: If the company state is nagivational, then simply remove the url definition in the company state and change the url defintion for the company.profile state to '/'. The only caveat for this solution would be the loss of the href attribute to be applied for for any anchor tags defined with the ui-sref="company" state which also implies the application of the text cursor. To mitigate this problem you might as well define all anchor tags with ui-sref attribute with a pointer cursor.

DEMO

CompanyCtrl.js

$stateProvider
    .state('company', {
        templateUrl: 'company.html',
        controller: 'CompanyCtrl as CompanyCtrl'
    });

CompanyProfileCtrl.js

$stateProvider
    .state('company.profile', {
        url: '/',
        templateUrl: 'profile.html',
        controller: 'CompanyProfileCtrl as CompanyProfileCtrl'
    })

style.css

a[ui-sref] {
  cursor: pointer;
}

UPDATE:

  1. Use Case: The same with use case #2 but making the company state an abstract state.

DEMO

CompanyCtrl.js

$stateProvider
    .state('company', {
        abstract: true,
        templateUrl: 'company.html',
        controller: 'CompanyCtrl as CompanyCtrl'
    });

Upvotes: 3

Related Questions