Using ui-router for “main” layout?

2019-07-22 16:27发布

问题:

I'm trying to create the 'main layout' for my page using ui-router views, but I can't seem to get it working right (various errors, controllers not getting called, templates not getting loaded).

<!DOCTYPE html>
<html ng-app="App">
    <head>
        ...
    </head>
    <body>
        <header ui-view="header">

        </header>

        <section ui-view="navigation">

        </section>

        <section ui-view="content">

        </section
    </body>
</html>

The idea is to have a state representing the "root" state for the whole site providing templates for navigation and header as well as a "root controller". Every other state loads it's content into the "content" view without affecting the others.

$stateProvider
    .state("index", {
        url: "/",
        controller: "App.IndexController",
        controllerAs: "vm",
        views: {
            "header@index" : { templateUrl: "app/main/header.html" }
            // nav etc.
        }

The app loads without any errors, but the templates as well as the controller never get invoked. Did I miss something?

I also saw that many people provide a separate "layout" view that get's loaded into an unnamed view (mostly on the <body> tag), but I consider this useless as the main index.html file is already my layout. Or: Is there a better way to achieve what I want?

回答1:

There is an answer Angular UI Router - Nested States with multiple layouts with a working plunker showing layout: http://plnkr.co/edit/I0BJ09BxR7nG9kZDeEIv?p=preview

The point is that there is index.html with

<div ui-view="layout"></div>

And the root state then injects into that ui-view="layout" its own template (layout) and also injects into layout views.

So firstly the layout template:

<div>
  <section class="top">
    <div ui-view="top"></div>
  </section>

  <section class="middle">

    <section class="left">
      <div ui-view="left"></div>
    </section>

    <section class="main">
      <div ui-view="main"></div>
    </section>

  </section>
</div>

And here is state def

$stateProvider
  .state('root', {
    url: '',
    views: {
      'layout': {
        templateUrl: 'partials/layout/1-column.html'
      },
      'header@root': {
        templateUrl: 'partials/layout/sections/header.html'
      },
      'footer@root': {
        templateUrl: 'partials/layout/sections/footer.html'
      }
    }
  })

And how it is working? we are using the absolute and relative target names.

View Names - Relative vs. Absolute Names

Behind the scenes, every view gets assigned an absolute name that follows a scheme of viewname@statename, where viewname is the name used in the view directive and state name is the state's absolute name, e.g. contact.item. You can also choose to write your view names in the absolute syntax.

For example, the previous example could also be written as:

  .state('report',{
    views: {
      'filters@': { },
      'tabledata@': { },
      'graph@': { }
    }
  })