Ответ 1
В документации angular.js по директивам
Когда директива использует
require
,$compile
выдаст ошибку, если указанный контроллер не найден. Префикс^
означает, что эта директива ищет контроллер у его родителей (без префикса^
, директива будет искать контроллер только для своего собственного элемента).
Так что в основном то, что вы пытаетесь сделать с тем, что братья и сестры напрямую общаются, невозможно. Я столкнулся с этой проблемой, но я не хотел использовать службу для общения. То, что я придумал, - это метод использования родительской директивы для управления связью между ее дочерними элементами, которые являются братьями и сестрами. Я отправил пример в 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
, тем самым вызывая метод child tive editItem
. Аналогично, сохранение данных работает одинаково в обратном порядке.
Обновить: Кстати, вот сообщение в блоге на coderwall.com, где я получил оригинальную идею с хорошими примерами require
и параметры контроллера в директивах. Тем не менее, его рекомендуемый синтаксис для последнего примера в этом сообщении не сработал у меня, поэтому я создал приведенный выше пример.