Comprendere l'opzione transclude della definizione della direttiva?


195

Penso che questo sia uno dei concetti più difficili da comprendere per me con la direttiva di angularjs.

Il documento da http://docs.angularjs.org/guide/directive dice:

transclude : compila il contenuto dell'elemento e rendilo disponibile alla direttiva. Utilizzato in genere con ngTransclude. Il vantaggio della inclusione è che la funzione di collegamento riceve una funzione di inclusione che è pre-vincolata all'ambito corretto. In una configurazione tipica il widget crea un ambito isolato, ma la inclusione non è un figlio, ma un fratello dell'ambito isolato. Ciò rende possibile che il widget abbia uno stato privato e che la trasclusione sia associata all'ambito padre (preisolato).

  • true: esclude il contenuto della direttiva.
  • "elemento": esclude l'intero elemento, comprese le direttive definite con priorità inferiore.

Si dice in transcludegenere utilizzato con ngTransclude. Ma l'esempio del documento di ngTransclude non usa affatto la ngTranscludedirettiva.

Vorrei alcuni buoni esempi per aiutarmi a capire questo. Perchè ne abbiamo bisogno? Che cosa risolve? Come usarlo?


FYI ... il link funziona almeno adesso
Sandy,

Risposte:


518

Considera una direttiva chiamata myDirective in un elemento e quell'elemento racchiude alcuni altri contenuti, diciamo:

<div my-directive>
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Se myDirective sta usando un modello, vedrai che il contenuto di <div my-directive>sarà sostituito dal tuo modello di direttiva. Quindi avendo:

app.directive('myDirective', function(){
    return{
        template: '<div class="something"> This is my directive content</div>'
    }
});

risulterà in questo rendering:

<div class="something"> This is my directive content</div> 

Si noti che il contenuto dell'elemento originale <div my-directive> andrà perso (o meglio, sostituito). Quindi saluta questi amici:

<button>some button</button>
<a href="#">and a link</a>

Quindi, se vuoi mantenere il tuo <button>...e <a href>...nel DOM? Avrai bisogno di qualcosa chiamato inclusione. Il concetto è piuttosto semplice: includi il contenuto da un posto all'altro . Quindi ora la tua direttiva sarà simile a questa:

app.directive('myDirective', function(){
    return{
        transclude: true,
        template: '<div class="something"> This is my directive content</div> <ng-transclude></ng-transclude>'
    }
});

Ciò renderebbe:

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>. 

In conclusione, in pratica usi transclude quando vuoi preservare il contenuto di un elemento quando usi una direttiva.

Il mio esempio di codice è qui . Potresti anche trarre vantaggio dal guardare questo .


12
Sembra che abbiano cambiato un po 'la funzionalità. Almeno nella versione> = 1.2.9. Il contenuto del modello non viene aggiunto al contenuto renderizzato. Vedi la risposta di @ TechExplorer in basso
Tarjei Romtveit,

20
Una risposta molto, molto buona. Molto al di sopra del normale. Hai buoni esempi e il tuo "questo è il contenuto della mia direttiva" ha reso molto facile la lettura nella versione renderizzata. Non capisco perché Angular debba usare una terminologia e concetti complessi e quindi non includere esempi di facile comprensione come il tuo. +2
freeall

Qualcuno sa se il contenuto escluso può fare riferimento ai campi dell'ambito di isolamento della direttiva? Dice sopra che la inclusione è un fratello, non un bambino, dell'ambito dell'isolato ... quindi presumo che non possa - ma mi chiedevo se qualcuno potesse confermare o farmi sapere se è possibile
Simon Green

@UladzimirHavenchyk grazie, hanno spostato il video in un altro posto. Ho corretto il link di conseguenza.
odiseo,

4
@odiseo, potresti per favore scrivere TUTTI i documenti angolari in un inglese semplice e semplice come questo! + molti 1.
Dan Hodson

76

Penso che sia importante menzionare i cambiamenti nel comportamento sopra nella nuova versione di AngularJS. Ho trascorso un'ora cercando di ottenere risultati sopra con Angular 1.2.10.

Il contenuto dell'elemento con ng-transclude non viene aggiunto ma completamente sostituito.

Quindi nell'esempio sopra, ciò che otterresti con "transclude" sarebbe:

<div class="something">
    <button>some button</button>
    <a href="#">and a link</a>
</div>

e non

<div class="something"> This is my directive content
    <button>some button</button>
    <a href="#">and a link</a>
</div>

Grazie.


Per ulteriori informazioni sul comportamento modificato in Angular 1.2, vedere change eed299a .
Mark Rajcok,

37

Ciò che TechExplorer dice è vero ma puoi avere entrambi i contenuti includendo nel tuo modello un semplice tag contenitore (come div o span) con l'attributo ng-transclude. Ciò significa che il seguente codice nel modello deve includere tutto il contenuto

<div class="something"> This is my directive content <div class="something" ng-transclude></div></div>

5
Quella era l'informazione chiave che mancava nelle altre risposte
Matheus,

4
Questa risposta aggiunge così tante informazioni. ng-transcludeè l'attributo che funge da segnaposto, all'interno del quale verrà inserito il contenuto escluso.
BeingSuman,

5

Da Wiki:

"Nell'informatica, la inclusione è l'inclusione parziale o totale di un documento elettronico in uno o più altri documenti per riferimento."

Vorrei aggiungere un altro uso per la inclusione, ovvero cambiare l'ordine di esecuzione delle funzioni di compilazione e collegamento delle direttive padre e figlio. Ciò può essere utile quando si desidera compilare il DOM figlio prima del DOM padre poiché il DOM padre dipende forse dal DOM figlio. Questo articolo è più approfondito e lo chiarisce molto bene!

http://www.jvandemo.com/the-nitty-gritty-of-compile-and-link-functions-inside-angularjs-directives-part-2-transclusion/


5

La documentazione aggiornata di AngularJS 1.6.6 ora ha una spiegazione migliore.

Transclude viene utilizzato per creare una direttiva che avvolge altri elementi

A volte è desiderabile essere in grado di passare un intero modello anziché una stringa o un oggetto. Diciamo che vogliamo creare un componente "finestra di dialogo". La finestra di dialogo dovrebbe essere in grado di racchiudere qualsiasi contenuto arbitrario.

Per fare ciò, dobbiamo usare l' opzione di esclusione . Fare riferimento all'esempio seguente.


script.js

angular.module('docsTransclusionExample', [])
.controller('Controller', ['$scope', function($scope) {
  $scope.name = 'Tobias';
}])
.directive('myDialog', function() {
  return {
    restrict: 'E',
    transclude: true,
    scope: {},
    templateUrl: 'my-dialog.html',
    link: function(scope) {
      scope.name = 'Jeff';
    }
  };
});

index.html

<div ng-controller="Controller">
  <my-dialog>Check out the contents, {{name}}!</my-dialog>
</div>

my-dialog.html

<div class="alert" ng-transclude></div>

Output compilato

<div ng-controller="Controller" class="ng-scope">
  <my-dialog class="ng-isolate-scope"><div class="alert" ng-transclude="">Check out the contents, Tobias!</div></my-dialog>
</div>

Transclude fa in modo che il contenuto di una direttiva con questa opzione abbia accesso al campo di applicazione al di fuori della direttiva anziché all'interno.

Questo è illustrato nell'esempio precedente. Si noti che abbiamo aggiunto una funzione di collegamento in script.js che ridefinisce il nome come Jeff. Di solito, ci aspetteremmo che {{name}} sia Jeff. Tuttavia, in questo esempio vediamo che l'associazione {{name}} è ancora Tobias.

Best practice : utilizzare solo transclude: truequando si desidera creare una direttiva che includa contenuti arbitrari.


0

transclude: true significa aggiungere tutti gli elementi definiti nella direttiva con l'elemento template della direttiva.

se transclude: false, questi elementi non sono inclusi nell'html finale della direttiva. Viene visualizzato solo il modello di direttiva.

transclude: element significa che il modello della direttiva non viene utilizzato, solo gli elementi definiti nella direttiva vengono visualizzati come HTML.

quando definisci la tua direttiva, dovrebbe essere limitata a E e quando la aggiungi a pagina allora

<my-directive><elements><my-directive>
<elements> is like <p>gratitude</p>
what i am talking about.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.