简体   繁体   中英

Angular UI-Router Multiple Named Views

Desired Behavior

I'm using AngularJS and the Angular UI-Router.

  1. I want to allow two child states to share a parent state.
  2. I want the child states to fill a ui-view in the parent state's view with their own view.
  3. I want one of the two child states to have three ui-view 's in their view, each filled with views.

Attempt at a diagram:

Parent: <ui-view>
        filled by
          Child:  <ui-view> <ui-view> <ui-view>
                    filled    filled   filled

Specific Details for My Situation

I have a state called category-details . Inside the view for this abstract state I have an unnamed ui-view . In one of the two child states ( category-details.selected ) I want to use multiple named views .

Current WORKING Strategy

Here is the abstract state. Very basic, but included for your reference.

.state('category-details', {
    abstract: true,
    data: {
        pageTitle: 'Category Details'
    },
    templateUrl: "views/category-details.html",
})

In the category-details.selected state (the state which will have multiple named views), I set the unnamed ui-view of category-details.html to category-details-selected.html :

.state('category-details.selected', {
    views: {
        '': {
            templateUrl: 'views/category-details-selected.html',
            controller: 'CategoryDetailsSelectedCtrl'
        }
    }
})

Inside of the category-details-selected.html view I have three named ui-views :

<div ui-view="firstNamedView"></div>
<div ui-view="secondNamedView"></div>
<div ui-view="thirdNamedView"></div>

Finally, I define a state for setting these three ui-view 's to meet the third part of my desired behavior:

.state('category-details.selected.aspect', {
    url:"/category-details/:selectedCategory",
    views: {
        'firstNamedView': {
            templateUrl: 'views/first-named-view.html',
            controller: 'FirstNamedViewCtrl'
        },
        'secondNamedView': {
            templateUrl: 'views/second-named-view.html',
            controller: 'SecondNamedViewCtrl'
        },
        'thirdNamedView': {
            templateUrl: 'views/third-named-view.html',
            controller: 'ThirdNamedViewCtrl'
        }
    }
});

Why My Solution is Awkward and Suboptimal

Adding the category-details.selected.aspect state to set constant elements (the three ui-view 's) of the category-details-selected view is unnecessary. It forces creating an extra state every time I want multiple named views.

What I've Tried

I believe I should be able to move the url and views of the category-details.selected.aspect state into the views component of its parent state ( category-details.selected ). This would look like:

.state('category-details.selected', {
    url:"/category-details/:selectedCategory",
    views: {
        '': {
            templateUrl: 'views/category-details-selected.html',
            controller: 'CategoryDetailsSelectedCtrl'
        },
        'firstNamedView': {
            templateUrl: 'views/first-named-view.html',
            controller: 'FirstNamedViewCtrl'
        },
        'secondNamedView': {
            templateUrl: 'views/second-named-view.html',
            controller: 'SecondNamedViewCtrl'
        },
        'thirdNamedView': {
            templateUrl: 'views/third-named-view.html',
            controller: 'ThirdNamedViewCtrl'
        }
    }
})

This resulted in the unnamed ui-view being set correctly, but the three named ui-view 's were not filled.

Since selecting the three named ui-view 's was the problem, I then attempted to select them with absolute selectors described here instead. This did not fix the problem. I tried:

firstNamedView
firstNamedView@
firstNamedView@category-details.selected
(others of course)

Closing Remarks

Is what I'm imagining possible, is another way better, or is my current method the best? It boils down to assigning the child ui-view s of a parent ui-view being set at the same time. I thought the last sentence was too confusing alone, so I included the entire example.

Please let me know if I can provide any more clarification such as versions. Thank you.

Abstract states need their own <ui-view/> for their children to plug into.

Parent state category-details is abstract state. Child state will need some reference ui-view to plug that state into. In your I believe the view /category-details.html does not any ui-view (as you have mentioned that category-details-selected.html contains the ui-view).

Try this:

.state('category-details', {
  abstract: true,
  data: {
    pageTitle: 'Category Details'
  },
  templateUrl: "views/category-details-selected.html",
})

.state('category-details.selected', {
  url:"/category-details/:selectedCategory",
  views: {       
    'firstNamedView': {
        templateUrl: 'views/first-named-view.html',
        controller: 'FirstNamedViewCtrl'
    },
    'secondNamedView': {
        templateUrl: 'views/second-named-view.html',
        controller: 'SecondNamedViewCtrl'
    },
    'thirdNamedView': {
        templateUrl: 'views/third-named-view.html',
        controller: 'ThirdNamedViewCtrl'
    }
  }
})

Here, we are giving abstract view a template, which has ui-view in it, for child to populate.

Have a look at documentation of ui-router: Abstract State for more information.


EDIT : I had assumed that views/category-details.html does not contain any ui-view. However, it was then pointed out that, views/views/category-details.html does have ui-view

This is what works for me:

category-details.html:

<div ui-view=""></div>

category-details-selected.html:

<div ui-view="firstNamedView"></div>
<div ui-view="secondNamedView"></div>
<div ui-view="thirdNamedView"></div>

router:

    .state('category-details', {
        abstract: true,
        data: {
            pageTitle: 'Category Details'
        },
        templateUrl: "../app/atest/category-details.html",
    })


    .state('category-details.selected', {
        url: "/atest",
        views: {
            '': {
                templateUrl: "../app/atest/category-details-selected.html",
                //   controller: 'approvalsCtrl as vm',
            },
            'firstNamedView@category-details.selected': {
                templateUrl: '../app/atest/first.html',
                //    controller: 'approvalsCtrl as vm',
            },
            'secondNamedView@category-details.selected': {
                templateUrl: '../app/atest/second.html',
                //   controller: 'approvalsCtrl as vm',
            },
            'thirdNamedView@category-details.selected': {
                templateUrl: '../app/atest/third.html',
                //   controller: 'approvalsCtrl as vm',
            }
        }
    })

I could see that you have mentioned you tried out using firstNamedView@category-details.selected , but it didn't worked for you. The above example is working for me. Check if you category-details.html and category-details-selected.html view contain proper ui-view .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM