问题
I believe I'm on the right track with these terms, "nested parameterized routes", but haven't found what I'm looking for yet.
My objective is to create intuitive routes for my API, something like the following example:
/api/v1/project/list
/api/v1/project/1/item/list
/api/v1/project/1/item/1/edit
/api/v1/project/2/item/3/delete
It's relatively easy and clear how to setup project states, but not the item states within each project.
{
state: 'project'
config: {
url:'/project'
}
},
{
state: 'project.list'
config: {
url: '/list'
}
},
{
state: 'project.detail'
config: {
url: '/:project_id'
}
}
It's not clear to me where to go from there so that items are relative or nested within projects.
回答1:
I'll assume you have a REST api (based on your example containing /api/v1
) which you want to expose/parallel as a UI. I'll assume you want to allow the user to drill down some hierarchical data model.
Choices!
There are many ways you could organize your states, for this drill-down list/details pattern. None is the "correct" way, but some are probably better than others. I will highlight two approaches that I've used:
Sibling states for list and details
One approach is to keep the "item list" states and "item details" states as siblings. This is what you did with project.list
and project.details
. This approach can be seen in the UI-Router Extras Demos source code.
When taking this approach
- you must take care to move the user from the list state to the detail state when drilling down.
- This approach has the benefit of easy-to-understand nesting of UI-Views. The ui-view for the detail view replaces the ui-view for the list view, when drilling down, because you are navigating to a sibling state.
- Your choice whether or not the detail for an entity also retrieves the list of sub-entities (does the detail for a project also show the items list for that product?)
States:
projectlist
// template plugs into parent ui-viewprojectdetail
// template plugs into parent ui-view, replacingprojectlist
projectdetail.itemslist
// template plugs into parent ui-view (@projectdetail
)projectdetail.itemdetail
// template plugs into parent ui-view (@projectdetail
), replacingitemslist
Details state as a substate of List state
Another approach is to make the detail state a child of the list state. This is organized similar to your REST routes.
When taking this approach
- States hierarchy closely resembles the REST routes being exposed
- Drilling down is simple and intuitive
- You must manage the visual display of list/detail.
- When drilling down from list state to the details substate, you probably want to hide the list.
- We use named views, and absolute naming in order to replace the parent list state's template with the template for the the detail state. This is called "view targetting".
States:
top
// theoretical parent statetop.projects
// lists projects. Plugs into parent ui-view (@top
)top.projects.project
// details for project. Its named view targets the grandparent ui-view (@top
), replacing the template fromtop.projects
list state.top.projects.project.items
// lists items. Plugs into parent ui-view (@top.projects.project
)top.projects.project.items.item
// details for item. Its named view targets the grandparent ui-view (@top.projects.project
), replacing the template fromtop.projects.project.items
list state.
Here's an example of using named view targeting to accomplish the second approach:
$stateProvider.state('top', {
url: '/',
template: '<ui-view/>',
});
$stateProvider.state('top.projects', {
url: '/projects',
resolve: {
projects: function(ProjectsRoute) {
return ProjectsRoute.getProjects();
}
},
controller: function($scope, projects) { $scope.projects = projects; },
template: '<li ng-repeat="project in projects"> <ui-view/>'
});
$stateProvider.state('top.projects.project', {
url: '/:projectid',
resolve: {
project: function(ProjectsRoute, $stateParams) {
return ProjectsRoute.getProject($stateParams.projectid);
}
}
views: {
'@top': {
controller: function($scope, project) { $scope.project = project; },
template: 'Project details: {{ project.name }} <a ui-sref=".items">view items</a> <ui-view/>'
}
});
$stateProvider.state('top.projects.project.items', {
url: '/projects',
resolve: {
items: function(ItemsRoute, project) {
return ItemsRoute.getItemsForProject(project.id);
}
},
controller: function($scope, items) { $scope.items = items; },
template: '<li ng-repeat="item in items"> <ui-view/>'
});
$stateProvider.state('top.projects.project.items.item', {
url: '/:itemid',
resolve: {
item: (ItemsRoute, $stateParams) {
return ItemsRoute.getItem($stateParams.itemid);
}
},
views: {
'@top.projects.project': {
controller: function($scope, item) { $scope.item = item; },
template: 'Item details: {{ item.name }}'
}
});
回答2:
I checked the Github Wiki, the Abstract States is enough.
来源:https://stackoverflow.com/questions/28662148/nested-parameterized-routes-with-ui-router-in-angularjs