2013-05-31 6 views
29

Я хотел бы получить доступ к области действия родительской директивы, но я не могу получить правильную комбинацию настроек. Возможно ли это, и это правильный подход?Доступ к родительскому охвату в директиве 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', 
    } 
}); 

Пожалуйста посмотреть fiddle

Благодаря

ответ

42

transclude: true С и scope: true, то parent директива создает две новые области применения: enter image description here

Scope 004 является результатом scope: true, и сфера применения 005 является результатом transclude: true. Так как директива child не создает новую область, она использует transcluded scope 005. Как видно из диаграммы, нет пути из области видимости 005 в область 004 (кроме как через private property $$ 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 на домашней странице Углового (пример «Создание компонентов»).

+0

@Mark Rajcok - Великий ответ Марк, ты похоже, один из немногих людей на этом сайте, который на самом деле полностью понимает Angular. У меня есть вопрос, похожий на этот, но по этой ссылке: [link] (http://stackoverflow.com/questions/23437113/get-property-value-from-parent-directive-within-child-directive). Моя проблема заключается в том, что к моменту, когда метод link работает в дочерней директиве, шаблон дочерней директивы уже был обработан. Это означает, что я не могу использовать родительское свойство внутри дочернего элемента для установки переменных области до рендеринга. –

+0

Это замечательно, но похоже, что это значение скопировано, а не связано (т. Е. Двусторонняя привязка данных). –

+0

Согласитесь, это не двусторонняя привязка данных. Чтобы ответить на исходный вопрос, дочерний контроллер просто должен получить доступ к области. $ Parent и имеет преимущества наследования и двусторонней привязки данных. – CarbonDry

9

Обычно путь вы получаете доступ к родительской переменной области видимости в директиве через двунаправленную привязку (scope:{model:'=model'} - см. the angular guide on directives) в конфигурации директивы), но поскольку вы используете переключение, это не так прямо. Если директива ребенок всегда будет ребенком родительской директивы вы можете однако настроить его, чтобы потребовать от родителей, а затем получить доступ к родительскому контроллера в функции ребенка ссылка:

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/

0

Существует пересылка fn в аргументах ссылки 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 
    } 
}); 
6

Я просто была такая же проблема, и, наконец, решить ее с угловым руководством;)

Короче говоря: вы должны использовать контроллер в ваш родитель директивы и требуют, что контроллер вребенок директива. Таким образом, вы сможете получить свои родительские свойства.

См 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', 
    } 
}); 
Смежные вопросы