Reputation: 15366
I have deeply nested routes, like
/customers
/customers/:customerId
/customers/:customerId/orders
/customers/:customerId/orders/:orderId
and, I have multiple named views: a header, a sidebar and main content.
// customers.html
<div ui-view="header">
<div ui-view="sidebar">
<div ui-view="content">
I'm trying to get a few requirements to work together:
customer
should be defined in all routes nested under /customers/:customerId
(i.e. a scope should be created with a controller that defines customer
)/customers/:customerId
and all three of the views should have access to customer
as defined by the parent.The first requirement I can achieve with:
$stateProvider
.state("customers", {
abstract: true,
url: "/customers/:customerId",
templateUrl: "customers.html",
controller: "CustomersController as vm"
})
.state("customers.details", {
url: "",
views: {header: ..., sidebar: ..., content: ...}
})
.state("customers.orders", {
url: "/orders",
views: {header: ..., sidebar: ..., content: ...} // these have to be defined again
})
Note that customers.orders
needs all three views defined again. That's not terrible, but I'm wondering if there's a better way. The only way I can figure is to have another level of state, but this seems worse because the state names include something that is not relevant to the state and is just a technical artifact ("default"):
$stateProvider
.state("customers", {
// as above
})
.state("customers.default", {
abstract: true,
views: {header: ..., sidebar: ..., content: ...}
})
.state("customers.default.details", {
url: "",
views: {content: ...} // don't have to define all three views!
})
Note that in my application I cannot flip the order and have something like app
, app.customers
and app.customers.details
, where app
provides the three default views and app.customers
provides the controller. The real application has defaults that I want to kick in at various depths of routing.
Upvotes: 0
Views: 106
Reputation: 4538
Here is a potential solution. I'm assuming that in your root html file, you have an unnamed ui-view. Let's say that this is your customer.html file:
<div ui-view="header">
<div ui-view="sidebar">
<div ui-view>
<div ui-view="content">
Your state config can be this:
$stateProvider
.state("customers", {
abstract: true,
url: "/customers/:customerId",
views: {
'': { // Populate root ui-view with customers.html
templateUrl: "customers.html",
controller: "CustomersController as vm"
},
'header@customers': { // Populate header ui-view in customers.html
...
},
'content@customers': {
...
},
'sidebar@customers': {
...
}
}
})
.state("customers.details", {
url: "",
views: {
'@customers': { // Populate unnamed ui-view in customers.html
...
}
}
})
.state("customers.orders", {
url: "/orders",
views: {
'@customers': {
...
}
}
})
This allows you to have the header, sidebar, and content ui-views remain constant for children of the customers state. Children can override each view individually if needed. Because all these views are nested, they would have access to the CustomersController as vm.
Upvotes: 1