Можно ли использовать $$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).