Подтвердить что ты не робот

Angular UI-Router Как создать "макет"?

Учитывая такой HTML файл:

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

Как создать состояние макета, заполняющего "заголовок" шаблоном заголовка, нижний колонтитул с помощью шаблона нижнего колонтитула, а затем разрешить дочерние состояния заполнять пустой ui-view?

Я полагаю, что пустой ui-view также можно назвать чем-то вроде ui-view = "main".

4b9b3361

Ответ 1

Один из способов - создать глобальное "корневое" состояние. Таким образом, каждое состояние будет дочерним. Как root.pages, root.pages.edit, root.settings и т.д. Затем вы можете предоставить шаблоны по умолчанию для верхнего и нижнего колонтитула.

Другим способом, другим подходом, который я использую лично, является использование ng-include для верхнего и нижнего колонтитула.

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

Btw. Я использую отдельный контроллер в header.tpl.html, который является дочерним элементом основного AppCtrl.:

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

Ответ 2

попробуйте это, практически ваши верхние и нижние колонтитулы являются статическими шаблонами, но вы можете добавить контроллеры, если вам нужно добавить к ним динамические функции, заголовок и нижний колонтитул будут включены по умолчанию, так как маршрут "', поэтому попробуйте:

 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: {
            '[email protected]': {
              templateUrl: 'homePage.html'
            }
          }
        })
        .state('root.other', {
          url: '/other',
          views: {
            '[email protected]': {
              templateUrl: 'other.html'
            }
          }
        });    

    }]);

Edit: для меня лучшим местом для установки представлений должно быть в index.html и что-то вроде этого кода:

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

Ответ 3

На самом деле есть очень простой способ сделать это.

1. Создание состояния макета

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

2. Использование неназванного состояния представления внутри макета

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

3. Создание состояния представления

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

4. Использовать именованное расположение макета как состояние root

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

Ответ 4

Основываясь на ответе Jack.the.ripper, я создал это решение.

Casus: У меня есть небольшая вариация, что я действительно хочу 2 макета. Один публичный и один частный. В Meteor с Blaze и Iron Router было хорошее решение, которое можно было бы определить, какой мастер-шаблон будет использоваться для определенного маршрута. Это я теперь смог создать благодаря Джеку!

ПРИМЕЧАНИЕ. Код будет в Jade и Coffee, а проект Meteor + Angular. Используйте 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:
          "[email protected]":
            templateUrl: 'client/views/home/home.html'
      )

      .state( 'public.login',
        url: '/login'
        views:
          "[email protected]":
            templateUrl: 'client/views/session/login.html'
      )
      $urlRouterProvider.otherwise '/'
 )

Это индексный файл, в котором определено представление приложения, которое будет использовать абстрактное состояние, определенное в маршрутизаторе.

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

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

Затем приватный макет с его видом контейнера.

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")

и, наконец, общий макет с его видом контейнера

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

С помощью этой настройки я могу установить страницу входа в систему, чтобы использовать абстрактный общий макет, указав в представлении этого маршрута, что он должен использовать view container @public, то есть из Public view, использовать контейнер Contain. В этом представлении загрузите login.html.

То же самое касается домашней страницы, которая загружает контейнер @private, что означает представление контейнера частного вида.

Это похоже на обаяние.

Большое спасибо Jack, а также автор ответа на Angular UI Router - вложенные государства с несколькими макетами, которые помогли мне добраться до окончательного решения.

Приветствия

Ответ 5

Как и в случае с jack.the.ripper, вы также можете делать это так, как это работает для меня.

app.config(function($stateProvider, $urlRouterProvider) {
  $stateProvider
    .state('root', {
      /* The Root State */
      views: {
        '': {
          abstract: true,
          templateUrl: 'master.html',
          controller: 'mainController'
        },
        '[email protected]': {
          templateUrl: 'header.html',
          controller: 'headerController',
        },
        '[email protected]': {
          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'
        }
      },
    });
});

В нашем index.html мы будем иметь только <ui-view></ui-view>

master.html будет выглядеть как

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

Почему я выбрал этот подход, мне не нужно создавать отдельный глобальный контроллер, а мой mainController будет глобальным контроллером.

Ответ 6

Вместо того, чтобы использовать маршруты вообще для верхнего и нижнего колонтитула, я бы использовал компоненты Angular теперь, когда они доступны в 1.5x.

Это более гибко, и вам не нужно иметь дело с root.whatever или ngInclude. Более подробно я расскажу здесь: fooobar.com/info/144209/..., но по существу вы:

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. Добавьте его на страницу index.html или аналогичную

<layout-header></layout-header>

3.

<layout-footer></layout-footer>

4. Результат в теле

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