Использование контроллера в качестве синтаксиса обновляет только одну из областей
Я немного запутался, когда дело доходит до controller as
синтаксис, как я никогда не работал с ним раньше. Я хотел бы знать правильный способ исправить это. Не удалось найти подобную проблему при поиске.
У меня есть меню и кнопка, которая переключает меню. У меню есть своя область действия, а у кнопки - другая, так как они находятся в двух отдельных файлах и контейнерах.
Когда я нажимаю кнопку, он только обновляет nav.isActive
в пределах кнопки. Я создал сервис для хранения состояния, что мне не нужно делать, когда я думаю об этом.. Должен ли я? Потому что единственный способ наблюдать, если это значение меняется, с помощью наблюдателя, который потребовал бы от меня использования $scope
поскольку this
не имеет $watch
Однако я хотел бы избежать этого настолько, насколько смогу, поскольку это повлияет на производительность, что важно в этом проекте.
Как правильно изменить переменную "scope" из другой "scope" при использовании controller as
синтаксис?
контроллер:
nav.controller('NavCtrl', ['navState', function(navState) {
var nav = this;
nav.menu = [
{icon: 'color_lens', href: ''},
{icon: 'color_lens', href: 'about'},
{icon: 'color_lens', href: 'contact'},
{icon: 'color_lens', href: 'logout'},
{icon: 'color_lens', href: 'faq'}
];
nav.toggleMenu = function() {
nav.isActive = navState.checkState();
}
}]);
Служба для передачи значения из одной области в другую:
nav.service('navState', [function() {
var isActive = false;
this.checkState = function() {
isActive = !isActive;
return !isActive;
}
}]);
Разметка меню (menu.html):
<nav class="si-wrapper si-dark" ng-controller="NavCtrl as nav" ng-class="{active: nav.isActive}">
<ul class="si-list">
<li class="si-item" ng-repeat="item in nav.menu">
<a href="#/{{item.href}}">
<div class="si-inner-item">
<i class="material-icons md-36" ng-bind="item.icon"></i>
</div>
</a>
</li>
</ul>
<h1>{{nav.isActive}}</h1> <!-- This doesn't change -->
</nav>
Кнопка, которая переключает меню (header.html):
<div ng-controller="NavCtrl as nav">
<button ng-click="nav.toggleMenu()">Toggle</button>
<span>{{nav.isActive}}</span> <!-- This updates however -->
</div>
2 ответа
Ваша проблема в том, что nav.isActive
не установлен для одного из контроллеров. В основном всякий раз, когда вы используете ng-controller
новый контроллер (и $scope
) создано. Так что для каждого из ваших контроллеров, $scope.isActive
должен быть установлен для связанного представления, чтобы ссылаться на него.
В вашем размещенном коде, isActive
устанавливается только когда toggleMenu()
выполняется, что происходит только в header.html.
Чтобы заставить ваш код работать, просто установите isActive
на нагрузке контроллера. Например:
nav.controller('NavCtrl', ['navState', function(navState) {
// put isActive on the scope on controller load
this.activeState = navState.getState();
nav.toggleMenu = function() {
navState.toggleState();
};
}]);
Вы должны улучшить свой сервис, разделив доступ к состоянию и манипуляцию с состоянием. Также, завернув его в объект контейнера, вы не будете иметь проблем с иерархией области видимости.
nav.service('navState', [function() {
var state = {
isActive: false
};
this.toggleState = function() {
state.isActive = !state.isActive;
};
this.getState = function(){
return state;
};
}]);
Затем вам нужно использовать `activeState.isActive 'внутри вашего представления.
Теперь у вас будет служба с разделяемым состоянием и два контроллера, которые ссылаются на одну и ту же службу при загрузке. Затем в представлении меню при переключении состояния обновляются обе области контроллеров.
Из документов angularjs:
Когда контроллер подключен к DOM через директиву ng-controller, Angular создаст новый объект Controller, используя указанную функцию конструктора Controller. Новая дочерняя область будет создана и сделана доступной в качестве параметра ввода для функции конструктора Контроллера как $scope.
Кроме того, директива ng-controller имеет область видимости, которая наследуется от родительской области видимости. Таким образом, вы также можете определить общие данные в родительском. Он будет доступен в области "NavCtrl". Но поскольку вы хотите использовать контроллер в качестве synax, одним из способов будет обмен данными с помощью службы.
Однако мне не нравится подход с директивой ng-controller. Другое решение состоит в том, чтобы заменить его иерархией директив, где дочерним директивам потребуется родительская директива. Также используйте свойство 'controllerAs' там.