Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs - ui.router sibling states

I'm using bootstrap with angularjs (and ui-router for routing).
I have a navbar where each tab click need to view another nested navbar in it. The nested navbar is a ui-view (should I do it differently?).
The problem is that when I click one li in the main navbar, all of the four nested navbar views are shown.

div(ng-controller='MyCtrl')
h1 Header
ul.nav.nav-tabs(role="tablist")
    li.active(role="presentation")
        a(ui-sref='first_nested_state') General
        div(ui-view)
    li.active.navbar-padding-left(role="presentation")
        a(ui-sref='second_nested_state') User
        div(ui-view)
    li.active.navbar-padding-left(role="presentation")
        a(ui-sref='third_nested_state') User
        div(ui-view)
    li.active.navbar-padding-left(role="presentation")
        a(ui-sref='fourth_nested_state') User
        div(ui-view)

And here is one nested navbar (they all look the same, except for the names):

div(ui-view)
ul.nav.nav-tabs(role="tablist", color="red")
  li.active(role="presentation")
     a(ng-href='#') A
  li.active(role="presentation")
     a(ng-href='#') B
  li.active(role="presentation")
     a(ng-href='#') C

And my state configuration:

 $stateProvider
    .state('main_nav_bar', {
          url: '/main_nav_bar',
          templateUrl: 'main_nav_bar.html'
      })
    .state('first_nested_navbar', {
        parent: 'main_nav_bar',
        url: '/first_nested_navbar',
        templateUrl: 'first_nested_navbar.html'
      })
    .state('second_nested_navbar', {
        parent: 'mainNavBar',
        url: '/second_nested_navbar',
        templateUrl: 'second_nested_navbar.html'
      })

I'm using coffeescript and jade as well.

like image 718
Gumba Avatar asked May 29 '26 18:05

Gumba


1 Answers

The issue here ("...when I click one <li>...all of the four nested navbar views are shown...") is related to repeated definition div(ui-view)

That means, that in the page DOM contains 4 <div ui-view></div>. All of them are used as a target for selected content. That's why we can see it rendered four times.

Solution should be in named views:

see: Multiple Named Views

In our case, we should use this HTML definition

li.active(role="presentation")
    a(ui-sref='first_nested_state') General
    div(ui-view="first") // give it name "first"
li.active.navbar-padding-left(role="presentation")
    a(ui-sref='second_nested_state') User
    div(ui-view="second") // give it name "second"
...

And use explicit views definitions of our states:

...
.state('first_nested_navbar', {
    parent: 'main_nav_bar',
    url: '/first_nested_navbar',
    views : {
      'first' : {   // now we explicitly inject into anchor/target "first"
        templateUrl: 'first_nested_navbar.html'
      },
    }
  })
.state('second_nested_navbar', {
    parent: 'mainNavBar',
    url: '/second_nested_navbar',
    views : {
      'second' : { // here we target the ui-view="second"
        templateUrl: 'second_nested_navbar.html'
      },
    }
  })

Check the really well documented example here, see the below snippet from that source:

$stateProvider
  .state('contacts', {
    // This will get automatically plugged into the unnamed ui-view 
    // of the parent state template. Since this is a top level state, 
    // its parent state template is index.html.
    templateUrl: 'contacts.html'   
  })
  .state('contacts.detail', {
    views: {
        ////////////////////////////////////
        // Relative Targeting             //
        // Targets parent state ui-view's //
        ////////////////////////////////////

        // Relatively targets the 'detail' view in this state's parent state, 'contacts'.
        // <div ui-view='detail'/> within contacts.html
        "detail" : { },            

        // Relatively targets the unnamed view in this state's parent state, 'contacts'.
        // <div ui-view/> within contacts.html
        "" : { }, 

        ///////////////////////////////////////////////////////
        // Absolute Targeting using '@'                      //
        // Targets any view within this state or an ancestor //
        ///////////////////////////////////////////////////////

        // Absolutely targets the 'info' view in this state, 'contacts.detail'.
        // <div ui-view='info'/> within contacts.detail.html
        "[email protected]" : { }

        // Absolutely targets the 'detail' view in the 'contacts' state.
        // <div ui-view='detail'/> within contacts.html
        "detail@contacts" : { }
like image 108
Radim Köhler Avatar answered May 31 '26 07:05

Radim Köhler