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".
Ответы
Ответ 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>