Pergunta

Eu tenho uma configuração muito simples:

<pane title="mytitle">Title in parent (transcluded): {{title}}</pane>

e

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

O plunker está aqui: http://plnkr.co/edit/yRHcNGjQAq1NHDTuwXku

A transclusão em si está funcionando, mas o {{title}} só é substituído no modelo da diretiva.
O {{title}} dentro do elemento transcluído, entretanto, permanece vazio, mesmo que a diretiva tenha uma variável title em seu escopo.Por que é que?

Foi útil?

Solução

O escopo do elemento transcluído não é um escopo filho da diretiva, mas um escopo irmão.Isto é o que a documentação diz:

Em uma configuração típica, o widget cria um escopo isolado, mas a transclusão não é filha, mas sim irmã do escopo isolado.

A solução mais simples neste caso, como você pode acessar o escopo transcutido, é assim:

.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;
        }
    };
});

Demonstração: http://plnkr.co/edit/ouq9B4F2qFPh557708Q1?p=preview

Outras dicas

@dfsq está correto sobre:

O escopo do elemento transludido não é um escopo infantil da diretiva, mas um irmão

Gostaria de adicionar mais comentários sobre por que esse é o comportamento esperado dos angularJs.Como diz a documentação:

Em uma configuração típica, o widget cria um escopo de isolado, mas a transclusão não é criança, mas um irmão do escopo de isolado.Isso possibilita que o widget tenha estado privado e a transclusão esteja ligada ao escopo dos pais (pré-isolado).

O conteúdo transcluído dentro da diretiva é arbitrário, não deveria temos conhecimento do âmbito de aplicação isolado da directiva, caso contrário, criaríamos uma código de acoplamento apertado.Porque para que o conteúdo transcluído funcione, o conteúdo deve conhecer os detalhes de implementação da sua diretiva (o que está disponível para uso).

Se você decidir que o conteúdo pertence à directiva.Você tem 2 opções:

1) Torne o conteúdo parte do modelo

    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>'
            };
   });

DEMONSTRAÇÃO

2) Use a trancclusão personalizada para vincular o escopo você mesmo:

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
           });
          }
        };
    });

DEMONSTRAÇÃO

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top