Nested parameterized routes with ui-router in AngularJS

不想你离开。 提交于 2020-01-02 09:56:42

问题


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-view
  • projectdetail // template plugs into parent ui-view, replacing projectlist
  • projectdetail.itemslist // template plugs into parent ui-view (@projectdetail)
  • projectdetail.itemdetail // template plugs into parent ui-view (@projectdetail), replacing itemslist

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 state
  • top.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 }}'
    }
});



回答2:


I checked the Github Wiki, the Abstract States is enough.



来源:https://stackoverflow.com/questions/28662148/nested-parameterized-routes-with-ui-router-in-angularjs

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!