角度ui路由器如何创建“布局”状态?

时间:2022-03-04 11:24:10

Given an HTML file like so:

给出这样的HTML文件:

<html>
<header ui-view="header"></header>
<div class="main" ui-view></div>
<footer ui-view="footer"></footer>
</html>

How would one create a layout state that fills the "header" with a header template, the footer with a footer template, and then allow child states to fill the empty ui-view?

如何创建一个布局状态,用页眉模板填充“页眉”,用页脚模板填充页脚,然后允许子状态填充空ui视图?

I suppose the empty ui-view could also be named something like ui-view="main".

我认为空的ui视图也可以命名为ui-view="main"。

6 个解决方案

#1


31  

One way is to make a global 'root' state. So, each and every state will be it's child. Like root.pages, root.pages.edit, root.settings, etc. Then you can provide default templates for header and footer.

一种方法是建立一个全局的“根”状态。每个州都是子州。像根。页,root.pages。编辑根。然后可以为页眉和页脚提供默认模板。

Another way, different approach, that I use personally, is to use ng-include for header and footer.

另一种方式,我个人使用的不同方法,是使用ng-include作为页眉和页脚。

<body ng-controller="AppCtrl">
  <div id="header" ng-include="'header.tpl.html'"></div>
  <div class="main_container" ui-view>
  </div>
</body>

Btw. I use seperate controller in header.tpl.html, that is a child of main AppCtrl.:

顺便说一句。我在header.tpl中使用seperate控制器。html,这是一个主应用程序的子。

<div id="header" ng-controller="HeaderCtrl"> ....

#2


77  

try this, practically your header and footer are static templates but you can add the controllers in case you need to add some dynamic functionality to it, the header and the footer will be included by default since the route is '', so try that out:

试试这个,实际上你的页眉和页脚是静态模板,但是如果你需要添加一些动态功能,你可以添加一些控制器,页眉和页脚会默认包含在其中,因为路径是“,所以试试:

 app.config(['$stateProvider', function($stateProvider){
        $stateProvider
        .state('root',{
          url: '',
          abstract: true,
          views: {
            'header': {
              templateUrl: 'header.html',
              controller: 'HeaderCtrl'
            },
            'footer':{
              templateUrl: 'footer.html',
              controller: 'FooterCtrl'
            }
          }
        })
        .state('root.home', {
          url: '/',
          views: {
            'container@': {
              templateUrl: 'homePage.html'
            }
          }
        })
        .state('root.other', {
          url: '/other',
          views: {
            'container@': {
              templateUrl: 'other.html'
            }
          }
        });    

    }]);

Edit: to me the best place to set the views should be in the index.html and something like this code:

编辑:对我来说,设置视图的最佳位置应该在索引中。html和类似的代码:

<header>
    <div ui-view="header"></div>
</header>
<div ui-view="container">
</div>
<footer id="mainFooter" ui-view="footer">
</footer>

#3


21  

There is actually a very easy way to do that.

其实有一个很简单的方法。

1. Create a layout state

1。创建一个布局状态

$stateProvider
  .state('master', {
    abstract: true,
    views: {
      layout: {
        templateUrl: '/layouts/master.html',
      }
    }
  });

2. Use unnamed view state inside the layout

2。在布局中使用未命名的视图状态。

<!-- layouts/master.html -->
<div ui-view></div>

3. Create a view state

3所示。创建一个视图状态

$stateProvider
  .state('home', {
    url: '/',
    templateUrl: '/views/home.html',
    parent: 'master',
  });

4. Use named layout state as root state

4所示。使用命名布局状态作为根状态

<!-- home.html -->
<body ui-view="layout"></body>

#4


5  

Based on the answer by Jack.the.ripper, I created this solution.

根据杰克的回答。开膛手,我创造了这个解决方案。

Casus: I have a slight variation that I actually want 2 layouts. One Public and one Private. In Meteor with Blaze and Iron Router there was a nice solution that you could just define which master template will be used for a certain route. This I have now been able to set up thanks to Jack!

开战者:我有一个小变化,我想要两个布局。一个是公共的,一个是私人的。在《流星》和《火焰和铁路由器》中,有一个很好的解决方案,你可以定义在某条路线上使用哪个主模板。多亏了杰克,我现在才得以建立这个网站!

NOTE: Code will be in Jade and Coffee and it's a Meteor + Angular project. Use http://js2.coffee/ to convert to Javascript.

注意:代码将在翡翠和咖啡,这是一个流星+角项目。使用http://js2。coffee/转换为Javascript。

# the ROUTER part
#
angular.module( 'myApp' ).config(

  ( $urlRouterProvider, $stateProvider, $locationProvider ) ->
    $locationProvider.html5Mode true

    $stateProvider
      .state( 'private',
        url: ''
        abstract: true
        views:
          'app':
            templateUrl: 'client/views/layouts/privateLayout.html'
      )

      .state( 'public',
        url: ''
        abstract: true
        views:
          'app':
            templateUrl: 'client/views/layouts/publicLayout.html'
      )

      .state( 'private.home',
        url: '/'
        views:
          "container@private":
            templateUrl: 'client/views/home/home.html'
      )

      .state( 'public.login',
        url: '/login'
        views:
          "container@public":
            templateUrl: 'client/views/session/login.html'
      )
      $urlRouterProvider.otherwise '/'
 )

This is the index file where the app view is defined that will utilise the abstract state defined in the router.

这是定义应用程序视图的索引文件,它将使用在路由器中定义的抽象状态。

head
meta(name="viewport" content="width=device-width, initial-scale=1")
base(href="/")

body(layout="column")
   div(ui-view="app" layout="column" flex)

Then the Private Layout with its container view.

然后是包含容器视图的私有布局。

div(layout="column" flex)
  div(ng-controller="AppCtrl" layout="row" flex)

  //- some private Layout stuff happening here....
  md-content(flex layout-padding)
     div(ui-view="container" layout="column")

and finally the Public Layout with its container view

最后是具有容器视图的公共布局

div.public-layout(layout="column" flex)
   div(ui-view="container" layout="column" flex)

With this setup I can set the login page to use the abstract public layout by stating in the view of this route that it should uses views container@public, meaning from Public view, use the view Container. In this view load the login.html.

通过这个设置,我可以设置登录页面来使用抽象的公共布局,方法是在该路径的视图中声明它应该使用views container@public,也就是说,从public view中使用view容器。在这个视图中,加载login.html。

Same goes for the home page, this one loads the container@private meaning the Container view of the Private view.

主页也是如此,这个装载container@private,也就是Private视图的容器视图。

This seems to work like a charm.

这似乎是一种魅力。

Thanks very much Jack, and also the author of the answer on Angular UI Router - Nested States with multiple layouts which helped me to get towards the final solution.

非常感谢Jack,还有关于角UI路由器的答案的作者——嵌套多个布局的状态,这帮助我找到了最终的解决方案。

Cheers

干杯

#5


1  

Similar to jack.the.ripper's way, you could also do it the way it works for me.

类似于jack.the。开膛手的方法,你也可以用我的方法。

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('root', {
      /* The Root State */
      views: {
        '': {
          abstract: true,
          templateUrl: 'master.html',
          controller: 'mainController'
        },
        'header@root': {
          templateUrl: 'header.html',
          controller: 'headerController',
        },
        'footer@root': {
          templateUrl: 'footer.html',
          controller: 'footerController'
        },
    },
   })
    .state('root.index', {
      /* The Index State */
      url: '/',
      views: {
        'content': {
          templateUrl: 'index.html',
          controller: 'indexController'
        }
      },
    .state('root.other', {
      /* The Other State */
      url: '/',
      views: {
        'content': {
          templateUrl: 'other.html',
          controller: 'otherController'
        }
      },
    });
});

In our index.html we will only have a <ui-view></ui-view>

在我们的索引中。我们只有一个

The master.html will look like

的主人。html的样子

<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>

Why I chose this approach, is I don't have to create a separate global controller, and my mainController will be the global controller.

为什么我选择这个方法,我不需要创建一个单独的全局控制器,而我的主控制器将是全局控制器。

#6


0  

Instead of using routes at all for the header and footer, I would use Angular components now that they are available in 1.5x.

我将不再使用所有的页眉和页脚的路径,现在我将使用它们在1.5x中可用的角度组件。

It is way more flexible and you don't have to deal with root.whatever or ngInclude. I go into it in more detail here: https://*.com/a/41093339/2416007, but essentially you:

这是一种更灵活的方法,你不需要处理root。不管或ngInclude。我在这里更详细地讲一下:https://*.com/a/41093339/2416007,但本质上你:

1. Create Component

1。创建组件

(function () {
'use strict';
angular
    .module('layout')
    .component('layoutHeader', {
        templateUrl: 'layout/header.html',
        bindings: {},
        controller: Controller
    });

Controller.$inject = [];
function Controller() {
    var ctrl = this;

    initialize();

    ////////////////////

    function initialize(){

    }

}
}());

2. Add it to your index.html page or similar

2。把它添加到索引中。html页面或类似的

<layout-header></layout-header>

3. Same for footer

3所示。相同的页脚

<layout-footer></layout-footer>

4. The result in the body is

4所示。身体的结果是

<layout-header></layout-header>
<main ui-view></main>
<layout-footer></layout-footer>

#1


31  

One way is to make a global 'root' state. So, each and every state will be it's child. Like root.pages, root.pages.edit, root.settings, etc. Then you can provide default templates for header and footer.

一种方法是建立一个全局的“根”状态。每个州都是子州。像根。页,root.pages。编辑根。然后可以为页眉和页脚提供默认模板。

Another way, different approach, that I use personally, is to use ng-include for header and footer.

另一种方式,我个人使用的不同方法,是使用ng-include作为页眉和页脚。

<body ng-controller="AppCtrl">
  <div id="header" ng-include="'header.tpl.html'"></div>
  <div class="main_container" ui-view>
  </div>
</body>

Btw. I use seperate controller in header.tpl.html, that is a child of main AppCtrl.:

顺便说一句。我在header.tpl中使用seperate控制器。html,这是一个主应用程序的子。

<div id="header" ng-controller="HeaderCtrl"> ....

#2


77  

try this, practically your header and footer are static templates but you can add the controllers in case you need to add some dynamic functionality to it, the header and the footer will be included by default since the route is '', so try that out:

试试这个,实际上你的页眉和页脚是静态模板,但是如果你需要添加一些动态功能,你可以添加一些控制器,页眉和页脚会默认包含在其中,因为路径是“,所以试试:

 app.config(['$stateProvider', function($stateProvider){
        $stateProvider
        .state('root',{
          url: '',
          abstract: true,
          views: {
            'header': {
              templateUrl: 'header.html',
              controller: 'HeaderCtrl'
            },
            'footer':{
              templateUrl: 'footer.html',
              controller: 'FooterCtrl'
            }
          }
        })
        .state('root.home', {
          url: '/',
          views: {
            'container@': {
              templateUrl: 'homePage.html'
            }
          }
        })
        .state('root.other', {
          url: '/other',
          views: {
            'container@': {
              templateUrl: 'other.html'
            }
          }
        });    

    }]);

Edit: to me the best place to set the views should be in the index.html and something like this code:

编辑:对我来说,设置视图的最佳位置应该在索引中。html和类似的代码:

<header>
    <div ui-view="header"></div>
</header>
<div ui-view="container">
</div>
<footer id="mainFooter" ui-view="footer">
</footer>

#3


21  

There is actually a very easy way to do that.

其实有一个很简单的方法。

1. Create a layout state

1。创建一个布局状态

$stateProvider
  .state('master', {
    abstract: true,
    views: {
      layout: {
        templateUrl: '/layouts/master.html',
      }
    }
  });

2. Use unnamed view state inside the layout

2。在布局中使用未命名的视图状态。

<!-- layouts/master.html -->
<div ui-view></div>

3. Create a view state

3所示。创建一个视图状态

$stateProvider
  .state('home', {
    url: '/',
    templateUrl: '/views/home.html',
    parent: 'master',
  });

4. Use named layout state as root state

4所示。使用命名布局状态作为根状态

<!-- home.html -->
<body ui-view="layout"></body>

#4


5  

Based on the answer by Jack.the.ripper, I created this solution.

根据杰克的回答。开膛手,我创造了这个解决方案。

Casus: I have a slight variation that I actually want 2 layouts. One Public and one Private. In Meteor with Blaze and Iron Router there was a nice solution that you could just define which master template will be used for a certain route. This I have now been able to set up thanks to Jack!

开战者:我有一个小变化,我想要两个布局。一个是公共的,一个是私人的。在《流星》和《火焰和铁路由器》中,有一个很好的解决方案,你可以定义在某条路线上使用哪个主模板。多亏了杰克,我现在才得以建立这个网站!

NOTE: Code will be in Jade and Coffee and it's a Meteor + Angular project. Use http://js2.coffee/ to convert to Javascript.

注意:代码将在翡翠和咖啡,这是一个流星+角项目。使用http://js2。coffee/转换为Javascript。

# the ROUTER part
#
angular.module( 'myApp' ).config(

  ( $urlRouterProvider, $stateProvider, $locationProvider ) ->
    $locationProvider.html5Mode true

    $stateProvider
      .state( 'private',
        url: ''
        abstract: true
        views:
          'app':
            templateUrl: 'client/views/layouts/privateLayout.html'
      )

      .state( 'public',
        url: ''
        abstract: true
        views:
          'app':
            templateUrl: 'client/views/layouts/publicLayout.html'
      )

      .state( 'private.home',
        url: '/'
        views:
          "container@private":
            templateUrl: 'client/views/home/home.html'
      )

      .state( 'public.login',
        url: '/login'
        views:
          "container@public":
            templateUrl: 'client/views/session/login.html'
      )
      $urlRouterProvider.otherwise '/'
 )

This is the index file where the app view is defined that will utilise the abstract state defined in the router.

这是定义应用程序视图的索引文件,它将使用在路由器中定义的抽象状态。

head
meta(name="viewport" content="width=device-width, initial-scale=1")
base(href="/")

body(layout="column")
   div(ui-view="app" layout="column" flex)

Then the Private Layout with its container view.

然后是包含容器视图的私有布局。

div(layout="column" flex)
  div(ng-controller="AppCtrl" layout="row" flex)

  //- some private Layout stuff happening here....
  md-content(flex layout-padding)
     div(ui-view="container" layout="column")

and finally the Public Layout with its container view

最后是具有容器视图的公共布局

div.public-layout(layout="column" flex)
   div(ui-view="container" layout="column" flex)

With this setup I can set the login page to use the abstract public layout by stating in the view of this route that it should uses views container@public, meaning from Public view, use the view Container. In this view load the login.html.

通过这个设置,我可以设置登录页面来使用抽象的公共布局,方法是在该路径的视图中声明它应该使用views container@public,也就是说,从public view中使用view容器。在这个视图中,加载login.html。

Same goes for the home page, this one loads the container@private meaning the Container view of the Private view.

主页也是如此,这个装载container@private,也就是Private视图的容器视图。

This seems to work like a charm.

这似乎是一种魅力。

Thanks very much Jack, and also the author of the answer on Angular UI Router - Nested States with multiple layouts which helped me to get towards the final solution.

非常感谢Jack,还有关于角UI路由器的答案的作者——嵌套多个布局的状态,这帮助我找到了最终的解决方案。

Cheers

干杯

#5


1  

Similar to jack.the.ripper's way, you could also do it the way it works for me.

类似于jack.the。开膛手的方法,你也可以用我的方法。

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('root', {
      /* The Root State */
      views: {
        '': {
          abstract: true,
          templateUrl: 'master.html',
          controller: 'mainController'
        },
        'header@root': {
          templateUrl: 'header.html',
          controller: 'headerController',
        },
        'footer@root': {
          templateUrl: 'footer.html',
          controller: 'footerController'
        },
    },
   })
    .state('root.index', {
      /* The Index State */
      url: '/',
      views: {
        'content': {
          templateUrl: 'index.html',
          controller: 'indexController'
        }
      },
    .state('root.other', {
      /* The Other State */
      url: '/',
      views: {
        'content': {
          templateUrl: 'other.html',
          controller: 'otherController'
        }
      },
    });
});

In our index.html we will only have a <ui-view></ui-view>

在我们的索引中。我们只有一个

The master.html will look like

的主人。html的样子

<div ui-view="header"></div>
<div ui-view="content"></div>
<div ui-view="footer"></div>

Why I chose this approach, is I don't have to create a separate global controller, and my mainController will be the global controller.

为什么我选择这个方法,我不需要创建一个单独的全局控制器,而我的主控制器将是全局控制器。

#6


0  

Instead of using routes at all for the header and footer, I would use Angular components now that they are available in 1.5x.

我将不再使用所有的页眉和页脚的路径,现在我将使用它们在1.5x中可用的角度组件。

It is way more flexible and you don't have to deal with root.whatever or ngInclude. I go into it in more detail here: https://*.com/a/41093339/2416007, but essentially you:

这是一种更灵活的方法,你不需要处理root。不管或ngInclude。我在这里更详细地讲一下:https://*.com/a/41093339/2416007,但本质上你:

1. Create Component

1。创建组件

(function () {
'use strict';
angular
    .module('layout')
    .component('layoutHeader', {
        templateUrl: 'layout/header.html',
        bindings: {},
        controller: Controller
    });

Controller.$inject = [];
function Controller() {
    var ctrl = this;

    initialize();

    ////////////////////

    function initialize(){

    }

}
}());

2. Add it to your index.html page or similar

2。把它添加到索引中。html页面或类似的

<layout-header></layout-header>

3. Same for footer

3所示。相同的页脚

<layout-footer></layout-footer>

4. The result in the body is

4所示。身体的结果是

<layout-header></layout-header>
<main ui-view></main>
<layout-footer></layout-footer>