嵌套角度状态的不同布局与ui-router?

时间:2014-07-04 00:09:16

标签: angularjs angular-ui-router

我的应用程序有四种逻辑状态:

pages.list      (lists pages)
pages.create    (create a new page)
pages.item      (show a single page)
pages.item.edit (edit a single page)

状态pages.listpages.item共享一个基本模板(传统的三列布局),但状态pages.createpages.item.edit具有完全不同的模板(完整页面编辑)。

用ui-router表达这个的最佳方法是什么?

2 个答案:

答案 0 :(得分:5)

我想说使用abstract states是可行的方法。在documentation中,他们清楚地概述了这些优点,其中一些非常适合您的用例(强调我的):

  

有关如何使用抽象状态的一些示例如下:

     
      
  • 为所有子状态网址添加网址。
  •   
  • 要插入一个模板,该模板具有自己的ui-view(s),其子状态将填充。   
        
    • (可选)将控制器分配给模板。控制器必须与模板配对。
    •   
    • 此外,将$ scope对象继承到子级,只需了解这是通过视图层次结构而不是状态层次结构发生的。
    •   
  •   
  • 通过解决方案提供已解决的依赖关系以供子状态使用。
  •   
  • 通过子状态或事件监听器使用的数据提供继承的自定义数据。
  •   
  • 运行可能以某种方式修改应用程序的onEnter或onExit函数。
  •   
  • 上述任意组合。
  •   

根据这种理解,您的应用程序可以按如下方式构建:


第1步

创建两个页面可以使用的模板。我们称他们为three_columns.htmlone_column.html。对于3列布局,请确保相应地命名ui-view

<!-- three_columns snippet -->
...
<body>
    <div ui-view="left"></div>
    <div ui-view="middle"></div>
    <div ui-view="right"></div>
</body>

然后,单列模板:

<!-- one_column snippet -->
...
<body>
    <div ui-view></div>
</body>

第2步

声明两个abstract states。我们称他们为oneColthreeCols。请注意,由于它们都声明了url: '/pages',因此所有继承的子状态都会自动将/pages添加到自己的网址中。

$stateProvider
  .state('oneCol', {
    abstract: true,
    url: '/pages',
    templateUrl: 'layouts/one_column.html'
}).state('threeCols', {
    abstract: true,
    url: '/pages',
    templateUrl: 'layouts/three_columns.html'
});

第3步

声明上述abstract states延伸的州。假设我们称他们为listcreateviewedit。在此,threeCols.listthreeCols.view必须声明3 templateUrl s,每个ui-view一个。另一方面,oneCol.createoneCol.edit会正常声明其未命名的templateUrl。我通常使用的约定是创建一个特定于每个州的文件夹,因为它有利于组织子视图模板:

$stateProvider
  .state('threeCols.list', {
    url: '/list',
    controller: 'ListCtrl',
    views: {
        'left': {
            templateUrl: 'modules/list/leftbar.html'
        },
        'middle': {
            templateUrl: 'modules/list/content.html'
        },
        'right': {
            templateUrl: 'modules/list/rightbar.html'
        }
    }
}).state('oneCol.create', {
    url: '/create',
    controller: 'CreateCtrl',
    templateUrl: 'modules/create/content.html'
}).state('threeCols.view', {
    url: '/view',
    controller: 'ViewCtrl',
    views: {
        'left': {
            templateUrl: 'modules/view/leftbar.html'
        },
        'middle': {
            templateUrl: 'modules/view/content.html'
        },
        'right': {
            templateUrl: 'modules/view/rightbar.html'
        }
    }
}).state('oneCol.edit', {
    url: '/edit',
    controller: 'EditCtrl',
    templateUrl: 'modules/edit/content.html'
});

有了这个,现在您的网址将如您所愿:/pages/list/pages/create/pages/view/pages/edit。您也可以根据需要创建和重复使用模板。

答案 1 :(得分:0)

我通常根据视图定义我的路线,而不是真正基于模型。例如,鉴于上面的简单解释,我将使用以下内容:

$stateProvider
    .state('pages.list', { url: '/list', controller: 'ListCtrl', templateUrl: 'threecol.html' })
    .state('pages.create', { url: '/create', controller: 'CreateCtrl', templateUrl: 'create.html' })
    .state('pages.item', { url: '/:itemId', controller: 'ItemCtrl', templateUrl: 'threecol.html' })
    .state('pages.edit', { url: '/:itemId/edit', controller: 'EditCtrl', templateUrl: 'edit.html' });

基本上,您可以使用threecol.html来定义常见的三列布局。 create.htmledit.html将是您的完整页面。

如果您想要围绕布局类型定义更抽象的方法,您还可以创建抽象父状态来定义布局本身。例如,您可以:

threecol.list
threecol.item
fullpage.create
fullpage.edit

如果您创建了threecolfullpage抽象状态,则可以定义常用的布局标记,并在需要的位置插入适当的<div ui-view=""></div>。这样,您可以为listitem使用不同的内容模板文件。