Из angular.js documentation on directives
Когда директива использует require
, $compile
выдаст ошибку, если указанный контроллер не найден. Префикс ^
означает, что эта директива осуществляет поиск контроллера у его родителей (без префикса ^
, директива будет искать контроллер только для собственного элемента).
Так что в основном то, что вы пытаетесь сделать, имея родных братьев, напрямую общается, невозможно. Я столкнулся с этой проблемой, но я не хотел использовать службу для общения. То, что я придумал, - это метод использования родительской директивы для управления связью между ее дочерними элементами, которые являются братьями и сестрами. Я опубликовал the example on github.
Что происходит, так это то, что оба ребенка требуют родителя (require: '^parentDirective'
) и собственного контроллера, оба из которых передаются в функцию связи. Оттуда каждый ребенок может получить ссылку на родительский контроллер и все его общедоступные методы, как на API.
Ниже один из детей itemEditor
function itemEditor() {
var directive = {
link: link,
scope: {},
controller: controller,
controllerAs: 'vm',
require: ['^itemManager', 'itemEditor'],
templateUrl: 'app/scripts/itemManager/itemManager.directives.itemEditor.html',
restrict: 'A'
};
return directive;
function link(scope, element, attrs, controllers) {
var itemManagerController = controllers[0];
var itemEditorController = controllers[1];
itemEditorController.itemManager = itemManagerController;
itemEditorController.initialize();
}
function controller() {
var vm = this;
// Properties
vm.itemManager = {};
vm.item = { id: -1, name: "", size: "" };
// Methods
vm.initialize = initialize;
vm.updateItem = updateItem;
vm.editItem = editItem;
// Functions
function initialize() {
vm.itemManager.respondToEditsWith(vm.editItem);
}
function updateItem() {
vm.itemManager.updateItem(vm.item);
vm.item = {};
}
function editItem(item) {
vm.item.id = item.id;
vm.item.name = item.name;
vm.item.size = item.size;
}
}
}
Обратите внимание, как значения, передаваемые в require
массива являются имя родительской директивы и название текущей директивы. Затем они доступны в функции link
через параметр controllers
. Назначьте контроллер родительской директивы как свойство текущего дочернего элемента, а затем его можно получить через функции контроллера ребенка через это свойство.
Также обратите внимание на функцию link
дочерней директивы Я вызываю функцию initialize
с контроллера ребенка. Это где часть линий связи установлена.
Я в основном говорю: в любое время, когда вы (родительская директива) получаете запрос на редактирование элемента, используйте этот мой метод с именем editItem
, который принимает параметр item
в качестве параметра.
Вот родительская директива
function itemManager() {
var directive = {
link: link,
controller: controller,
controllerAs: 'vm',
templateUrl: 'app/scripts/itemManager/itemManager.directives.itemManager.html',
restrict: 'A'
};
return directive;
function link(scope, element, attrs, controller) {
}
function controller() {
var vm = this;
vm.updateMethod = null;
vm.editMethod = null;
vm.updateItem = updateItem;
vm.editItem = editItem;
vm.respondToUpdatesWith = respondToUpdatesWith;
vm.respondToEditsWith = respondToEditsWith;
function updateItem(item) {
vm.updateMethod(item);
}
function editItem(item) {
vm.editMethod(item);
}
function respondToUpdatesWith(method) {
vm.updateMethod = method;
}
function respondToEditsWith(method) {
vm.editMethod = method;
}
}
}
Здесь в родительских вы можете увидеть, что respondToEditsWith
принимает метод в качестве параметра и присваивает это значение своего свойства editMethod
. Это свойство вызывается всякий раз, когда вызывается метод контроллера editItem
и объект item
передается ему, тем самым вызывая метод editItem
дочерней директивы. Аналогично, сохранение данных работает одинаково в обратном порядке.
Update: Кстати, вот a blog post on coderwall.com где я получил оригинальную идею с хорошими примерами require
и опций контроллера в директивах. Тем не менее, его рекомендуемый синтаксис для последнего примера в этом сообщении не сработал для меня, поэтому я создал приведенный выше пример.
Полагаете, вы сказали, что для совместного использования контроллеров они должны быть в одной и той же директиве. Возможно, вам будет проще использовать $ broadcast и $ emit. –