Списки, связанные с директивой / контроллером родного брата (и мастер / деталь) в Angular
У меня есть примерно четыре основные пары связанных директив, которые одновременно отображаются в моем пользовательском интерфейсе AngularJS. Вообще говоря, каждая пара включает в себя директиву родительского списка сверху, с которой связана директива подробного редактора, как показано на этой диаграмме:
Каждый правый список имеет отношение многие-к-одному с активным левым выбором, и всегда должны отображаться связанные данные. Как мне обновлять связанный список (ассоциация слева направо)?
В настоящее время каждая пара директив master-detail, или "стек", совместно использует сервис. Этот сервис держит itemState.active
(активная подробная запись) и itemState.headers
(список основных результатов запроса). Активность в основной или подробной панели вызывает службу, которая напрямую влияет на состояние службы. Затем связь мастера / детали управляется с помощью простых декларативных часов Angular на этом общем positionService.state
; код контроллера практически не требуется. Я ожидаю, что использование сервиса в качестве единой точки правды позволит мне в будущем интегрировать отображение, близкое к реальному, например, через SignalR
, Эта реализация master-detail представлена здесь только для фона, хотя я приветствую улучшения:
Мастер Директива, напримерposition-list.js
templateUrl: "position/position-list.html",
controller: ['$scope', 'positionSvc', function ($scope, positionService) {
$scope.positions = positionService.itemState();
$scope.select = function (position) {
positionService.read(position.id)
};
}
Мастер-шаблон, напримерposition-list.html
<li ng-repeat="i in itemState.headers" ng-click="select(i)">{{i.title}}</li>
Сервис, напримерposition-svc.js
this.itemState = {
headers: [],
active: { id: 0 },
pending: httpSvc.pending
};
this.create = function (detail) {
httpSvc.remote("post", detail).then(function (header) {
itemState.headers.unshift(header);
read(detail.id);
});
}
this.read = function (id) {
httpSvc.remote("get", id).then(function (detail) {
itemState.active = detail;
});
}
Аналогичная директива и шаблон существуют для деталей. Он разделяет тот же сервис. Вы поняли идею.
Сейчас я ищу приемлемый способ обработки событий влево - вправо, следуя хорошим методам проектирования и хорошо известным шаблонам AngularJS. Я хотел бы сохранить сочетаемость моих директив.
Чтобы продемонстрировать, что я не ищу, чтобы вы делали мою работу за меня (и организовывали свои собственные мысли), вот несколько подходов, которые я придумал, хотя ни один из них пока не показался правильным. Я продолжаю документировать их, проверьте, не нужен ли этот раздел. Они сгруппированы по пути сообщения:
- leftController -> mainApp -> rightController
- часть a: leftController -> mainApp
mainApp.$scope.onLeftItemSelected
(например, через{ scope: '&' }
)leftController.$scope.$emit
вleftController.watch
leftController.$parent.onLeftItemSelected
(например, AngularJS обращается к родительской области из дочернего контроллера, но неправильно создает восходящую зависимость)
- часть b: mainApp -> rightController
mainApp.$scope.$broadcast
mainApp.rightService.load(leftItemId)
- часть a: leftController -> mainApp
- leftController -> mainApp model -> rightController. $ watch
- разделить родительскую переменную области видимости между leftController и rightController
- передать изолированную область видимости из левого контроллера в mainApp, используя
{ scope: '=' }
; это решение Хесуса Кинтаны ниже и здесь: http://plnkr.co/edit/tyZPziT9VoWDFqHdF8A5?p=preview
- leftController -> $ route -> rightController
- Реализация этого могла бы быть идеальной, позволяя мне обеспечить глубокое связывание / создание закладок в моем одностраничном приложении, но требует, чтобы страница загружала родительскую иерархию при выборе дочернего элемента, а не только наоборот (загрузка дочерних записей выбранный родительский элемент). это требует больших начальных инвестиций, чем я могу оправдать в настоящее время. http://embed.plnkr.co/DBSbiV/preview
- leftService -> rightService
- Введите
nominationService
также в братаpositionService
, ВызовnominationService.load(positionid)
при настройкеpositionService.activeRecord
, Pro: уже работает. Con: Это неправильно. Эта родственная зависимость делает родительский список неиспользуемым. - добавить пользовательскую службу Pub/Sub ( /questions/48062494/angularjs-dvunapravlennaya-svyaz-mezhdu-dvumya-oblastyami-kontrollerami-cherez-servis, http://jsfiddle.net/ThomasBurleson/sv7D5/)
- Введите
- leftService -> $ rootScope.broadcast -> rightService
- не идеально, предполагая, что наша строка события будет уникальной в корневом пространстве имен (но проблемы производительности были решены, как обсуждено здесь /questions/22511646/kak-pravilno-obschatsya-mezhdu-kontrollerami-v-angularjs)
- leftService -> mainApp -> rightService
- Введите
positionService
а такжеnominationService
вmainApp
, Добавить простой список событий вpositionService
передать уведомление вверх. PRO: это сохраняет роль leftService как единой точки правды для активной записи по всему приложению (как отметил Мартин Кортез в комментариях ниже)
- Введите
- leftService -> $ rootScope. $ route -> rightController -> rightService
- см. примечания к подходу 3
Ссылки передают данные между контроллерами. Как общаться между контроллерами, не используя SharedService между ними?
1 ответ
Основанный на дизайне угловых шаблонов, наилучшим способом является директива bind scope с помощью '=' (двухстороннее связывание), а внутри директив создается $scope.# Watch для обнаружения изменений привязки элемента и выполнения функции действия с учетом переменной,
Является более чистым способом связи внутри обеих директив, угловое обнаружение изменений и распространение на директивы ботов.
Извините, если ответ бесполезен, но вопрос не очень хорошо объяснить.