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.
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.
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:
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
States:
projectlist // template plugs into parent ui-viewprojectdetail // template plugs into parent ui-view, replacing projectlistprojectdetail.itemslist // template plugs into parent ui-view (@projectdetail)projectdetail.itemdetail // template plugs into parent ui-view (@projectdetail), replacing itemslistAnother 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:
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 from top.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 from top.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 }}'
}
});
I checked the Github Wiki, the Abstract States is enough.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With