Динамический класс корпуса с интерфейсом Angular UI-Router
Я пытаюсь найти элегантный способ иметь настраиваемый динамический класс тега body, который я могу легко установить из ui-router configurations
, и если ни один не установлен, я могу использовать значение по умолчанию или нет.
Пример:
routes.js
$stateProvider
.state('login', {
url: "/login",
template: 'Login'
})
.state('register', {
url: "/register",
template: 'Register'
}).
.state('profile', {
url: "/profile",
template: 'Profile'
});;
Простая разметка HTML
<html>
<body class=""> <!-- Dynamically class to change -->
<div ui-view></div>
</body>
</html>
Сценарий:
1 - Посещение state
входа. Я должен иметь класс тела, равный auth
2 - Посещая регистр state
, он будет иметь тот же класс auth
3 - При посещении профиля state
тело будет иметь класс по умолчанию или none
Как вы это достигаете?
Ответы
Ответ 1
У вас может быть мастер AppController, который контролирует это:
<html ng-app="app" ng-controller="AppController as appController">
...
<body class="{{ appController.bodyClasses }}">
Внутри AppController:
var vm = this;
vm.bodyClasses = 'default';
// this'll be called on every state change in the app
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams){
if (angular.isDefined(toState.data.bodyClasses)) {
vm.bodyClasses = toState.data.bodyClasses;
return;
}
vm.bodyClasses = 'default';
});
Внутри вашего маршрута defs:
.state('register', {
url: "/register",
template: 'Register',
data: {
bodyClasses: 'auth'
}
});
Подробнее об этой стратегии атрибутов данных см. Документация UI Router.
Ответ 2
Здесь аналогичный подход, как @jmq, используя данные состояния, но реализованный как директива вместо контроллера. (Самое приятное в директиве - вы можете применить это к любым произвольным элементам)
Пример разметки
<body ng-app="app" route-css-classnames>
Конфигурация маршрутов (routes.js)
$stateProvider
.state('login', {
url: "/login",
template: 'Login',
data : {
cssClassnames : 'auth'
}
})
.state('register', {
url: "/register",
template: 'Register',
data : {
cssClassnames : 'auth'
}
}).
.state('profile', {
url: "/profile",
template: 'Profile'
});
Директива (routeCssClassnames.js)
(function () {
'use strict';
angular.module('shared').directive('routeCssClassnames', routeCssClassnames);
function routeCssClassnames($rootScope) {
return {
restrict: 'A',
scope: {},
link: function (scope, elem, attr, ctrl) {
$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {
var fromClassnames = angular.isDefined(fromState.data) && angular.isDefined(fromState.data.cssClassnames) ? fromState.data.cssClassnames : null;
var toClassnames = angular.isDefined(toState.data) && angular.isDefined(toState.data.cssClassnames) ? toState.data.cssClassnames : null;
// don't do anything if they are the same
if (fromClassnames != toClassnames) {
if (fromClassnames) {
elem.removeClass(fromClassnames);
}
if (toClassnames) {
elem.addClass(toClassnames);
}
}
});
}
}
}
}());
Ответ 3
Вы также можете применить это на свой тег тела или там, где вам это нужно.
ng-class="$state.current.name"