Transclusion and scopes in angular: Why is this not working?

前端 未结 2 684
忘掉有多难
忘掉有多难 2021-01-23 02:25

I have a very simple setup:

Title in parent (transcluded): {{title}}

and

angular.mo         


        
相关标签:
2条回答
  • 2021-01-23 02:26

    The scope of the transcluded element is not a child scope of the directive but a sibling one. This is what documentation says:

    In a typical setup the widget creates an isolate scope, but the transclusion is not a child, but a sibling of the isolate scope.

    The simplest solution in this case how you can access transcuded scope is like this:

    .directive('pane', function () {
        return {
            restrict: 'E',
            transclude: true,
            scope: {
                title: '@'
            },
            template:
                '<div>' +
                    '<div>Title in isolated scope: {{title}}</div>' +
                    '<div ng-transclude></div>' +
                '</div>',
            link: function (scope, element, attrs) {
                scope.$$nextSibling.title = attrs.title;
            }
        };
    });
    

    Demo: http://plnkr.co/edit/ouq9B4F2qFPh557708Q1?p=preview

    0 讨论(0)
  • 2021-01-23 02:34

    @dfsq is correct about:

    The scope of the transcluded element is not a child scope of the directive but a sibling one

    I'd like to add more comments why this is the expected behavior of angularJs. As the docs says:

    In a typical setup the widget creates an isolate scope, but the transclusion is not a child, but a sibling of the isolate scope. This makes it possible for the widget to have private state, and the transclusion to be bound to the parent (pre-isolate) scope.

    The transcluded content inside the directive is arbitrary, it should not have knowledge about the directive's isolate scope, otherwise, we would create a tight coupling code. Because for the transcluded content to work, the content must know the implementation details of your directive (what is available to use).

    If you decide that the content belongs to the directive. You have 2 options:

    1) Make the content part of the template

        angular.module('transclude', [])
             .directive('pane', function(){
                return {
                  restrict: 'E',
                  transclude: true,
                  scope: { title:'@' },
                  template: '<div>' +
                              '<div>Title in isolated scope: {{title}}</div>' +
                              '<div>' +
                                 ' Title in parent (transcluded): {{title}} ' +
                             ' </div>' +
                            '</div>'
                };
       });
    

    DEMO

    2) Use custom tranclusion to bind the scope yourself:

    angular.module('transclude', [])
         .directive('pane', function(){
            return {
              restrict: 'E',
              transclude: true,
              scope: { title:'@' },
              template: '<div>' +
                          '<div>Title in isolated scope: {{title}}</div>' +
                          '<div class="transclude"></div>' +
                        '</div>',
            link: function (scope, element, attr,controller, linker) {
               linker(scope, function(clone){
                      element.find(".transclude").append(clone); // add to DOM
               });
              }
            };
        });
    

    DEMO

    0 讨论(0)
提交回复
热议问题