Можно ли использовать $$prevSibling для доступа к данным области в директиве "transcluded"?
моя настройка директивы выглядит следующим образом:
<div data-directive-a data-value="#33ff33" data-checked="true">
<div data-directive-b></div>
</div>
- я использую transclusion для обеспечения
directiveBотрисовывается. -
directiveAимеет флажок, который предназначен для изменения некоторого значения всякий раз, когда он установлен. - это значение должно быть доступно в
directiveAиdirectiveB's область.
мне удалось это сделать, но только путем ссылки $$prevSibling - есть ли лучший способ?
вот код: http://jsfiddle.net/janeklb/yugQf/ (в этом примере нажатие флажка просто означает "очистить" значение)
--
немного больше глубины:
"Содержание"directiveA (то, что трансцендируется в него) не всегда directiveB. Другое directiveB-подобные директивы также окажутся там. The directiveB "типы" всегда будут использоваться в directiveA.
2 ответов
чтобы избежать слишком большого соединения ваших компонентов, я бы избегал использования $$prevSibling. Лучшее решение с вашего directiveB-ожидается, что подобные компоненты будут использоваться в directiveA компоненты-использовать require.
.directive( 'directiveB', function () {
return {
require: '^directiveA',
scope: true,
link: function ( scope, element, attrs, directiveA ) {
scope.obj = directiveA.getObj();
}
};
})
на ^require указывает, что где-то на элементе этой директивы или на любом элементе над ней в иерархии DOM есть директива под названием directiveA, и мы хотим вызвать методы на своем контроллере.
.directive( 'directiveA', function () {
return {
// ...
controller: function ( $scope ) {
// ...
this.getObj = function () {
return $scope.obj;
};
}
};
})
так что теперь в directiveB вы может использовать ng-model="obj.attr".
есть много вариантов этого, но, учитывая, насколько общим был вопрос, я считаю, что это лучший подход. Вот обновленная Скрипка:http://jsfiddle.net/yugQf/7/.
@Josh упомянул в своем ответе, что
лучшее решение с вашего
directiveB-ожидается, что подобные компоненты будут использоваться вdirectiveAкомпоненты-использоватьrequire.
я играл с этим, и я считаю, что контроллер на directiveA - это только решение (так +1 Джош). Вот как выглядят области, использующие скрипку OP:

(обратная коричневая стрелка и у вас есть $$previousSibling вместо $$ / / сделать.)
кроме $$previousSibling, область 004 не имеет пути для изоляции области 003. Обратите внимание, что объем 004-это раскрываемый область,directiveA создает, и с directiveB не создает новую область, эта область также используется directiveB.
так как объект, который вы хотите поделиться с directiveB создано в directiveAконтроллер, мы также не можем использовать атрибуты для обмена данными между директивами.
создание модели внутри a директива, а затем делиться этой моделью с внешним миром довольно нетипично. Как правило, вы хотите определить свои модели вне ваших директив и даже вне ваших контроллеров (послушайте несколько минут Misko). Услуги часто являются хорошим местом для хранения ваших моделей/данных. Контроллеры обычно должны ссылаться на части модели(моделей), которые необходимо спроецировать в представление, с которым они связаны.
для простоты, я собираюсь определить модель на контроллере директивы будут обращаться к этой модели обычным способом. В педагогических целях,directiveA по-прежнему будет использовать область изолирования и directiveB создаст новую дочернюю область с помощью scope: new как в ответе @Josh. Но любой тип (изолировать, новый ребенок, без новой области) и комбинация будут работать, теперь, когда у нас есть модель, определенная в родителе масштаб.
Ctrl:
$scope.model = {value: '#33ff33', checkedState = true};
HTML-код:
<div ng-controller="NoTouchPrevSibling">
<div data-directive-a data-value="model.value" data-checked="model.checkedState">
<div data-directive-b></div>
</div>
по другим педагогическим причинам я решил передать directiveA два свойства модели как отдельные атрибуты, но вся модель/объект также могли быть переданы. Поскольку directiveB создаст дочернюю область, ему не нужно передавать какие-либо атрибуты, поскольку он имеет доступ ко всей области родителя / контроллера свойства.
директивы:
app.directive('directiveA', function () {
return {
template: '<div>'
+ 'inside parent directive: {{checkedState}}'
+ '<input type="checkbox" ng-model="checkedState" />'
+ '<div ng-transclude></div>'
+ '</div>',
transclude: true,
replace: true,
scope: {
value: '=',
checkedState: '=checked'
},
};
});
app.directive('directiveB', function () {
return {
template: '<div>'
+ '<span>inside transcluded directive: {{model.checkedState}}</span>'
+ '<input type="text" ng-model="model.value" />'
+ '</div>',
replace: true,
scope: true
};
});
области:

обратите внимание, что дочерняя область directiveB (006) наследуется от области трансклюзии directiveA (005).
после нажатия флажка и изменения значения в текстовом поле:

обратите внимание, что угловые ручки обновляют свойства области изоляции. Нормальный прототип JavaScript наследство предоставляет дочерней области directiveB доступ к model в области контроллера (003).