Como usar o recurso 'substituir' para diretivas AngularJS personalizadas?

91

Por que causa replace=trueou replace=falsenão impacto no código abaixo?

Por que "algum conteúdo existente" não está sendo exibido quando replace = false?

Ou, colocando de forma mais humilde, você poderia explicar qual é o replace=true/falserecurso nas diretivas e como usá-lo?

Exemplo

JS / Angular:

<script>
    angular.module('scopes', [])
          .controller('Ctrl', function($scope) {
                $scope.title = "hello";

          })
          .directive('myDir', function() {
            return {
              restrict: 'E',
              replace: true,
              template: '<div>{{title}}</div>'
            };
      });
</script>

HTML:

<div ng-controller="Ctrl">
    <my-dir><h3>some existing content</h3></my-dir>
</div>

Veja no Plunker aqui:

http://plnkr.co/edit/4ywZGwfsKHLAoGL38vvW?p=preview

Kaya Toast
fonte
2
@georgeawg marcou isto como duplicado de outra pergunta que foi feita / respondida em uma data posterior a esta pergunta.
Kaya Toast de

Respostas:

189

Quando você replace: trueobtiver a seguinte parte do DOM:

<div ng-controller="Ctrl" class="ng-scope">
    <div class="ng-binding">hello</div>
</div>

Considerando que, com replace: falsevocê, obtenha isto:

<div ng-controller="Ctrl" class="ng-scope">
    <my-dir>
        <div class="ng-binding">hello</div>
    </my-dir>
</div>

Portanto, a replacepropriedade nas diretivas refere-se a se o elemento ao qual a diretiva está sendo aplicada ( <my-dir>nesse caso) deve permanecer ( replace: false) e o modelo da diretiva deve ser anexado como seu filho,

OU

o elemento ao qual a diretiva está sendo aplicada deve ser substituído (replace: true ) pelo modelo da diretiva.

Em ambos os casos, os filhos do elemento (aos quais a diretiva está sendo aplicada) serão perdidos. Se você quisesse preservar o conteúdo original do elemento / filhos, você teria que traduzi-lo. A seguinte diretiva faria isso:

.directive('myDir', function() {
    return {
        restrict: 'E',
        replace: false,
        transclude: true,
        template: '<div>{{title}}<div ng-transclude></div></div>'
    };
});

Nesse caso, se no modelo da diretiva você tiver um elemento (ou elementos) com atributo ng-transclude, seu conteúdo será substituído pelo conteúdo original do elemento (ao qual a diretiva está sendo aplicada).

Veja o exemplo de translusão http://plnkr.co/edit/2DJQydBjgwj9vExLn3Ik?p=preview

Veja isto para ler mais sobre translusão.

Kamilkp
fonte
6
Esta é uma explicação maravilhosamente simples. E muito obrigado por esclarecer a transclusão também.
Kaya Toast
Mais importante, por que não está explicado em docs.angularjs.org/guide/directive e por que esta resposta não leva a uma resposta definitiva sobre o assunto?
Trindaz de
3
@Trindaz replaceestá obsoleto desde AngularJS v1.3 ( link ).
Tonči D.
33

replace:true está obsoleto

Do Docs:

replace ([DESCONTINUADO!], Será removido na próxima versão principal - ou seja, v2.0)

especifique o que o modelo deve substituir. O padrão é false.

  • true - o modelo substituirá o elemento da diretiva.
  • false - o modelo substituirá o conteúdo do elemento da diretiva.

- API de diretiva abrangente AngularJS

Do GitHub:

Caitp-- Está obsoleto porque existem problemas conhecidos, muito bobos replace: true, alguns dos quais não podem ser corrigidos de uma maneira razoável. Se você for cuidadoso e evitar esses problemas, terá mais poder para você, mas para o benefício dos novos usuários, é mais fácil simplesmente dizer "isso vai te dar dor de cabeça, não faça".

- AngularJS Issue # 7636


Atualizar

Nota: replace: trueestá obsoleto e não é recomendado para uso, principalmente devido aos problemas listados aqui. Ele foi completamente removido no novo Angular.

Problemas com substituir: verdadeiro

Para mais informações, veja

georgeawg
fonte
2
Eu continuo lendo que isso deveria ter suporte não oficial no Angular 2, mas não consigo descobrir como ativá-lo. Alguém pode me dizer qual é a sintaxe?
devios1
@devios Eu preciso disso para meus componentes MDL, mas atualmente usando a remove-hostsolução alternativa stackoverflow.com/questions/34280475/… se você descobrir como ativar replace: trueem A2, nos informe.
kuncevic.dev