Взаимодействие контроллеров друг с другом
Всем привет
Интересует вопрос взаимодействия "несвязанных" друг с другом контроллеров. Упрощенный пример верстки: <div ng-controller="Controller1" ng-scope> ... some </div> ... <div ng-controller="Controller2" ng-scope> ... some </div> Насколько я понимаю, "по-феншую" в ангуляре для взаимодействия контроллеров я должен использовать "объект-посредник":
angular
.module( 'app', [])
.factory( '$mediator', function() {
return { /* code */ };
})
.controller( 'Controller1', function( $scope, $mediator ) {
var model = $scope.model = {};
})
.controller( 'Controller2', function( $scope, $mediator ) {
var model = $scope.model = {};
});
Я и не против. В чем проблема: приходится периодически обмениваться сообщениями/данными одному контроллеру с другим или наоборот. Для этих целей создаю изолированный scope и использую его реализацию подписки на события и поджиг событий. Выглядит это так:
angular
.module( 'app', [])
.factory( '$mediator', function( $rootScope ) {
return $rootScope.$new( true ); // isolate
})
.controller( 'Controller1', function( $scope, $mediator ) {
var model = $scope.model = {
field: null
};
// subscribe to event
$mediator.$on( 'my:event', function( event, data ) {
// ...
});
})
.controller( 'Controller2', function( $scope, $mediator ) {
var model = $scope.model = {
field: null
};
// fire event
$mediator.$emit( 'my:event', 'data' );
});
Работает, но: поджиг события в изолированном scope ($mediator) вызывает пересчет обработчиков всего приложения при данной реализации, а этого хотелось бы избежать. Кто-что думает на этот счет? Возможно, все проще, чем кажется :) Только не надо предлагать для обмена событиями обещания. Они, насколько мне известно, "одноразовые". Спасибо ) |
$emit Передает событие вверх по иерархии областей
broadcast Передает событие вниз для всех дочерних областях (и их детей) http://jsfiddle.net/simpulton/XqDxG/ В примере rootScope применяется но можно и изолированный использовать. а еще можно так
<!doctype html>
<html ng-app="project">
<head>
<title>Angular: Service example</title>
<script src="http://code.angularjs.org/angular-1.0.1.js"></script>
<script>
var projectModule = angular.module('project',[]);
projectModule.factory('theService', function() {
return {
thing : {
x : 100
}
};
});
function FirstCtrl($scope, theService) {
$scope.thing = theService.thing;
$scope.name = "First Controller";
}
function SecondCtrl($scope, theService) {
$scope.someThing = theService.thing;
$scope.name = "Second Controller!";
}
</script>
</head>
<body>
<div ng-controller="FirstCtrl">
<h2>{{name}}</h2>
<input ng-model="thing.x"/>
</div>
<div ng-controller="SecondCtrl">
<h2>{{name}}</h2>
<input ng-model="someThing.x"/>
</div>
</body>
</html>
|
Цитата:
1. Я создаю изолированный scope. Какой вверх/вниз? :) 2. Я отключил ControllerTwo от подписки на событие http://jsfiddle.net/XqDxG/528/ При каждом клике по кнопке, происходит пересчет отключенного "контроллера". Как этого избежать? |
ты меня озадачил)
я тоже недоумеваю почему он срабатывает. Как еще один вариант пиши свой Observable Пример для читателей, нерв и сам напишет :)
factory( '$mediator', function() {
return {
events:{},
fire:function(name,param){
var listeners=this.events[name],
length=listeners.length,
i=0;
for(;i<length;i++){
listeners[i](param)
}
},
on:function(name,callback) {
this.events[name]=events[name]||[];
this.events[name].push(callback);
}
}
})
|
ГЫГЫ.
посмотри вот на этот эксперемент Твой медиатор вообще не при делах Ни чего в голову кроме отказа от ng show не приходит. Тобиш замены ngshow на
$scope.$watch('message',function(){
alert('изменился message')
//тут какой то аналог ng show
});
watch работает корректно. Интересно заглянуть внутрь ng show и узнать в чем секрет его поведения :) Взглянул, https://github.com/angular/angular.j...ShowHide.js#L3 ГЫГЫГЫ :) |
Цитата:
Цитата:
|
Взглянул, https://github.com/angular/angular.j...ShowHide.js#L3 :)
Ты функцию слушаеш, единственный способ узнать что она вернула это выполнить ее http://jsfiddle.net/ThpUH/ То есть ангуляр действует абсолютно логично так как выяснить что возвращает функция можно только через вызов функции. А вдруг ты через фабрику связал контролы, откуда ангуляр знает ? Вот он и вызывает ту функцию которую ты прописал так как другого варианта выяснить нет. Замени в ngShow функцию на свойство, и оперируй свойством если не хочешь чтобы при каждом обновлении дергалась функция |
Так-так-так. А чем обычный объект-посредник не угодил? Не могу понять, зачем здесь, вообще, события? Какая практическая задача?
|
Цитата:
Разумеется, скролл я слушаю с... эм... скажем так, не на каждое событие скролла тригерю событие (потому, что их очень много и часто), а только на последнее. |
Цитата:
А, вообще, в Ангуляр не мешало бы добавить директиву для скроллинга для навешивания на window, textarea и т.п. |
Цитата:
Цитата:
Цитата:
.directive( 'ngScroll', [ '$timeout', '$document', function( $timeout, $document ) {
return {
link: function( scope, element ) {
var timer = { cancel: angular.noop };
element = element[ 0 ].tagName === 'HTML' ? $document : element;
element.bind( 'scroll', function() {
var elem = element[ 0 ].documentElement ? element[ 0 ].documentElement : element[ 0 ];
$timeout.cancel( timer );
timer = $timeout(function() {
scope.$emit( 'event:name', {
scrollTop: element.scrollTop(),
scrollLeft: element.scrollLeft(),
scrollHeight: elem.scrollHeight,
scrollWidth: elem.scrollWidth,
clientHeight: elem.clientHeight,
clientWidth: elem.clientWidth
});
}, 200 );
});
}
};
}]);
|
Наверное, лучше слать значения хотя бы раз в 50 мс) А, вообще, время должно подстраиваться под скорость прокрутки: если большая, то чаще.
Всё недоумеваю по поводу этой штуки: cancel(promise) в $timeout, может быть мне кто-нибудь объяснит как обещание может остановить само себя? Обещание специально делают так, чтобы оно не содержало методов деферред-объекта, а они, по сути, сломали паттерн... |
Цитата:
На мой взгляд правильней разнести на 2 директивы, или директиву и сервис. Первая - ng-scroll - просто висит на элементе и шлет события без фильтрации; вторая зависит от первой (required), фильтрует события полученные от первой (если надо) и вычисляет значения прокрутки (в моем случае). Цитата:
Цитата:
|
| Часовой пояс GMT +3, время: 07:13. |