Доступ к родительской области в директиве Transcluded
Я хотел бы получить доступ к области действия родительской директивы, но я не могу получить правильную комбинацию настроек. Это возможно и это правильный подход?
Я действительно хочу не помещать что-то вроде SOME_CONST (что помогло бы мне делать обновления DOM через поток управления) в MyCtrl
<div ng-controller="MyCtrl">
<parent>
<child></child>
</parent>
</div>
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.obj = {prop:'foo'};
}
myApp.directive('parent', function() {
return {
scope: true,
transclude: true,
restrict: 'EA',
template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
link: function(scope, elem, attrs) {
scope.SOME_CONST = 'someConst';
}
}
});
myApp.directive('child', function() {
return {
restrict: 'EA',
template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{SOME_CONST}}. I really don\'t want to put everything inside the MyCtrl',
}
});
Пожалуйста, посмотрите эту скрипку
Спасибо
4 ответа
С transclude: true
а также scope: true
, parent
Директива создает две новые области:
Область 004 является результатом scope: true
и объем 005 является результатом transclude: true
, Так как child
Директива не создает новую область, она использует включенную область 005. Как видно из диаграммы, пути из области 005 в область 004 нет (кроме как через частное свойство $$prevSibling, которое идет в противоположном направлении от $$nextSibling). - но не используйте их.)
Решение @joakimbl здесь, вероятно, лучше, хотя я думаю, что более распространенным является определение API на контроллере родительской директивы, а не определение свойств на this
:
controller: function($scope) {
$scope.SOME_CONST = 'someConst';
this.getConst = function() {
return $scope.SOME_CONST;
}
}
Тогда в child
директива:
link:function(scope,element,attrs,parentCtrl){
scope.SOME_CONST = parentCtrl.getConst();
},
Вот как tabs
а также pane
Директивы работают на домашней странице Angular (пример "Создание компонентов").
Обычно доступ к родительской переменной в директиве осуществляется через двунаправленную привязку (scope:{model:'=model'}
- см. угловой справочник по директивам) в конфигурации директив), но поскольку вы используете transclusion, это не так просто. Если дочерняя директива всегда будет дочерней по отношению к родительской директиве, вы можете настроить ее так, чтобы она требовала родителя, а затем получить доступ к родительскому контроллеру в функции дочерней ссылки:
myApp.directive('parent', function() {
return {
scope: true,
transclude: true,
restrict: 'EA',
template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
controller: function($scope) {
$scope.SOME_CONST = 'someConst';
this.SOME_CONST = $scope.SOME_CONST;
}
}
});
myApp.directive('child', function() {
return {
restrict: 'EA',
require:'^parent',
scope:true,
link:function(scope,element,attrs,parentCtrl){
scope.SOME_CONST = parentCtrl.SOME_CONST;
},
template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{SOME_CONST}}. I really don\'t want to put everything inside the MyCtrl',
}
});
Смотрите это обновление: http://jsfiddle.net/uN2uv/
У меня была такая же проблема, и я наконец решил ее с помощью углового руководства;)
Вкратце: вам нужно использовать контроллер в вашей родительской директиве и требовать этого контроллера в вашей дочерней директиве. Таким образом, вы можете получить родительские свойства.
См. https://docs.angularjs.org/guide/directive Глава: Создание директив, которые сообщают
Я изменил вашу скрипку, чтобы использовать контроллер, теперь вы можете получить доступ к своей константе: https://jsfiddle.net/bbrqdmt3/1/
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.obj = {prop:'foo'};
}
myApp.directive('parent', function() {
return {
scope: true,
transclude: true,
restrict: 'EA',
template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
controller: function($scope) {
this.getConst= function() {
return 'someConst';
}
},
}
});
myApp.directive('child', function() {
return {
restrict: 'EA',
require : '^parent',
link: function(scope, element, attrs, ctrl) {
scope.value= ctrl.getConst();
},
template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t. I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function? is this even a good idea? {{value}}. I really don\'t want to put everything inside the MyCtrl',
}
});
В аргументах ссылки fn после контроллера есть transclude fn.
myApp.directive('parent', function() {
return {
scope: true,
transclude: true,
restrict: 'EA',
template: '<div><h1>I'm a parent header.</h1></div>',
link: function (scope, el, attrs, ctrl, transclude) {
transclude(scope, function (clone, scope) {
element.append(clone); // <-- will transclude it's own scope
});
},
controller: function($scope) {
$scope.parent = {
binding: 'I\'m a parent binding'
};
}
}
});
myApp.directive('child', function() {
return {
restrict: 'EA',
require:'^parent',
scope:true,
link:function(scope,element,attrs,parentCtrl){
},
template: '<div>{{parent.binding}}</div>' // <-- has access to parent's scope
}
});