Por que o escopo do ng-transclude não é filho do escopo de sua diretiva – se a diretiva tem um escopo isolado?

Dada uma diretiva ( container1 ) com transclude e um escopo isolado, quando a diretiva está vinculada, eu tenho esses escopos:

 Scope 004 <-- scope of the body Scope 005 <-- scope of directive container1 Scope 006 <-- scope of the ng-transclude 

Eu esperava:

 Scope 004 <-- scope of the body Scope 005 <-- scope of the directive Scope 006 <-- scope of the ng-transclude 

Se a mesma diretiva tiver um escopo compartilhado em vez de um escopo isolado , obtenho o resultado esperado.

Isso me causa um problema porque, se o conteúdo transcluído contém outra diretiva ( component1 ) com um escopo isolado, recebo:

 Scope 004 <-- scope of the body Scope 005 <-- scope of the directive Scope 006 <-- scope of the ng-transclude Scope 007 <-- scope of directive component1 

Eu quero usar as diretivas como esta:

    

Mas isso não funciona, dentro de component1 , $scope.data é undefined porque objectExposedInContainer1 não está no escopo direito.

Eu tenho duas perguntas:

  • Por que o escopo do ng-transclude não é filho do escopo de sua diretiva se a diretiva tiver um escopo isolado? Isso é um inseto?
  • Se não for um bug, como uma diretiva de contêiner pode passar dados para seu conteúdo, se não definir atributos como eu tentei.

Aqui está uma amostra em que não funciona: http://plnkr.co/edit/NDmJiRzTF9e5gw8Buht2?p=preview . Como o Plunker é construído com o Anguar, é difícil depurar com o Batarang. Eu recomendo baixar o código localmente. Comente a line 10 do app.js para que funcione usando um escopo compartilhado.

Por que o escopo do ng-transclude não é filho do escopo de sua diretiva se a diretiva tiver um escopo isolado?

ng-transclude projetado para permitir que diretivas trabalhem com conteúdo arbitrário, e escopos isolados são projetados para permitir que diretivas encapsulem seus dados.

Se ng-transclude não preservasse escopos como esse, qualquer conteúdo arbitrário que você estivesse transcluindo precisaria conhecer os detalhes de implementação de sua diretiva (ou seja, precisaria saber o que está disponível no escopo isolado que você criou).

Se não for um bug, como uma diretiva de contêiner pode passar dados para seu conteúdo, se não definir atributos como eu tentei.

Se a diretiva de contêineres e as diretivas contidas estiverem acopladas – ou seja, você escreveu as duas e precisa que elas atuem juntas -, elas devem se comunicar por meio de um controlador compartilhado.

Se a diretiva de contêiner deve injetar conteúdo no escopo dos filhos (por exemplo, ng-repeat), então você não deveria estar usando um escopo isolado.


A documentação angular é bastante clara sobre o que o comportamento deve ser:

“Em uma configuração típica, o widget cria um escopo isolado, mas a transclusão não é um filho, mas um irmão do escopo isolado. Isso possibilita que o widget tenha um estado privado e a transclusão seja vinculada ao pai ( pré-isolado).

você pode transcluir manualmente o elemento filho

 link: function(scope, element, attrs, ctrl, transclude) { transclude(scope, function(clone, scope) { element.find('.transclude-placeholder').append(clone); }); } 

A resposta principal é correta apenas para Angular até v1.2.

Desde a versão v1.3 do Angular, o comportamento mudou e agora se comporta exatamente como descrito na parte “Eu esperava” da pergunta, tornando essa questão obsoleta para o Angular v1.3 +.

Fonte: https://github.com/angular/angular.js/commit/fb0c77f0b66ed757a56af13f81b943419fdcbd7f