Множество применений AngularJS для контроллеров и rootScope
Я хочу использовать контроллер на 2 отдельных элементах HTML и использовать $rootScope, чтобы сохранить 2 списка в синхронизации при редактировании:
HTML
<ul class="nav" ng-controller="Menu">
<li ng-repeat="item in menu">
<a href="{{item.href}}">{{item.title}}</a>
</li>
</ul>
<div ng-controller="Menu">
<input type="text" id="newItem" value="" />
<input type="submit" ng-click="addItem()" />
<ul class="nav" ng-controller="Menu">
<li ng-repeat="item in menu">
<a href="{{item.href}}">{{item.title}}</a>
</li>
</ul>
</div>
JS
angular.module('menuApp', ['menuServices']).
run(function($rootScope){
$rootScope.menu = [];
});
angular.module('menuServices', ['ngResource']).
factory('MenuData', function ($resource) {
return $resource(
'/tool/menu.cfc',
{
returnFormat: 'json'
},
{
getMenu: {
method: 'GET',
params: {method: 'getMenu'}
},
addItem: {
method: 'GET',
params: {method: 'addItem'}
}
}
);
});
function Menu($scope, MenuData) {
// attempt to add new item
$scope.addNewItem = function(){
var thisItem = $('#newItem').val();
MenuData.addItem({item: thisItem},function(data){
$scope.updateMenu();
});
}
$scope.updateMenu = function() {
MenuData.getMenu({},function(data){
$scope.menu = data.MENU;
});
}
// get menu data
$scope.updateMenu();
}
Когда страница загружается, и UL
и DIV
отображают правильное содержимое из базы данных, но когда я использую метод addNewItem()
, обновляется только DIV
.
Есть ли лучший способ структурировать мою логику или я могу что-то сделать, чтобы убедиться, что $scope.menu
в UL
обновляется одновременно?
Вот пример чего-то подобного: http://plnkr.co/edit/2a55gq
Ответы
Ответ 1
Я бы предложил использовать службу, содержащую меню и его методы. Служба обновит меню, на которое ссылается контроллер (ы).
Смотрите рабочий плункер здесь: http://plnkr.co/edit/Bzjruq
Это пример кода JavaScript:
angular
.module( 'sampleApp', [] )
.service( 'MenuService', [ '$rootScope', function( $rootScope ) {
return {
menu: [ 'item 1' ],
add: function( item ) {
this.menu.push( item );
}
};
}])
.controller( 'ControllerA', [ 'MenuService', '$scope', function( MenuService, $scope ) {
$scope.menu = MenuService.menu;
$scope.addItem = function() {
MenuService.add( $scope.newItem );
};
}]);
И образец страницы Html:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-app="sampleApp">
<div ng-controller="ControllerA">
<ul>
<li ng-repeat="item in menu">{{item}}</li>
</ul>
<input type="text" ng-model="newItem" /><input type="submit" ng-click="addItem()" />
</div>
<div ng-controller="ControllerA">
<ul>
<li ng-repeat="item in menu">{{item}}</li>
</ul>
</div>
</body>
</html>
Ответ 2
Изменить:
Вот обновленная версия plunker. он работает в двух контроллерах.
Основная идея - использовать службу и широковещать для синхронизации данных с директивой.
app.service('syncSRV', function ($rootScope) {
"use strict";
this.sync = function (data) {
this.syncData = data;
$rootScope.$broadcast('updated');
};
});
app.controller('MainCtrl1', ['$scope', function ($scope) {
}])
.controller('MainCtrl2', ['$scope', function ($scope) {
}]);
app.directive('sync',function (syncSRV) {
"use strict";
return {
template: '<div><input ng-model="syncdata" type="text" /></div> ',
controller: function ($scope, $element, $attrs) {
$scope.$watch('syncdata', function (newVal, oldVal, $scope) {
syncSRV.sync(newVal);
}, true);
}
};
}).directive('dataview', function (syncSRV) {
"use strict";
return {
template: '<div>Sync data : {{data}}</div> ',
controller: function ($scope, $element, $attrs) {
$scope.$on('updated', function () {
$scope.data = syncSRV.syncData;
});
}
};
});
<div ng-controller="MainCtrl1">
<fieldset>
<legend> Controller 1</legend>
<div dataview></div>
<div sync></div>
</fieldset>
</div>
<div ng-controller="MainCtrl2">
<fieldset>
<legend> Controller 2</legend>
<div dataview></div>
<div sync></div>
</fieldset>
</div>
Вот что я сделал бы для этого случая.
Я создам директиву для
<ul class="nav" ng-controller="Menu">
<li ng-repeat="item in menu">
<a href="{{item.href}}">{{item.title}}</a>
</li>
</ul>
поэтому после обновления элемента он будет обновлен в обеих директивах.
небольшой пример
Ответ 3
Я просто хочу обновить и упростить выбранный ответ. Кажется, вы можете уменьшить это, удалив эту строку:
$rootScope.$broadcast( 'MenuService.update', this.menu );
и этот фрагмент:
$scope.$on( 'MenuService.update', function( event, menu ) {
$scope.menu = menu;
});
Причина в том, что мы уже пользуемся Сервисом и в основном привязываем два идентичных контроллера, поэтому не нужно использовать $rootScope. $broadcast и добавлять наблюдаемые.
Рабочий плунж здесь:
http://plnkr.co/edit/1efEwU?p=preview
Вам нужно всего лишь связать службу, когда я реорганизую код, я смог уменьшить его до 13 строк вместо 22.