2013-10-16 14 views
13

Esiste un modo per escludere del contenuto in una direttiva senza aggiungere elementi aggiuntivi.Transclude in AngularJS senza aggiungere nuovo elemento

Per esempio

direttiva:

{ 
    scope: { 
     someParam: "=" 
    }, 
    link: function(scope, element, attrs){ 
     //do something 
    }, 
    transclude: true, 
    template:'<div ng-transclude></div>' 
} 

sorgente html:

<div my-directive some-param="somethingFromController"> 
    my transcluded content: {{somethingElseFromController}} 
</div> 

Con questo esempio un div in più viene aggiunto al markup. Normalmente questo andrebbe bene ma sto provando a usare questa direttiva all'interno di una tabella, quindi aggiungere un tag div avvita le cose.

Ho anche provato a non specificare transclude o template che elimina il tag div extra ma ora non è possibile trovare {{somethingElseFromController}} poiché il contenuto "transcluded" è in un ambito isolato. So che potrei ottenere i parametri per la mia direttiva dall'oggetto attrs nella funzione di collegamento invece di creare un ambito isolato, ma preferirei evitare di dover valutare le stringhe con scope. $ Apply().

Qualcuno sa come realizzare questo? Grazie!

+0

Qual è il contenuto "transclusa" che 'somethingElseFromController' è destinato a fornire? –

+0

Potrebbe essere qualsiasi cosa. per esempio. una stringa dal controller. Ho solo bisogno che il mio contenuto escluso sia nello stesso ambito del controller. – rob

+1

angular necessita di un elemento per "appendere" l'ambito. Tuttavia, se stai solo cercando di aggiungere un comportamento, allora come hai detto, non hai bisogno di un modello. Sì, altrimenti usa l'ambito genitore. –

risposta

7

Questo è effettivamente possibile con Angular. Direttive come ng-repeat lo fanno. Ecco come lo fai:

{ 
    restrict: 'A', 
    transclude: true, 
    compile: function (tElement, attrs, transclude) { 
     return function ($scope) { 
      transclude($scope, function (clone) { 
       tElement.append(clone); 
      }); 
     }; 
    } 
}; 

Quindi cosa sta succedendo qui? Durante il collegamento, stiamo semplicemente aggiungendo il clone, che è l'elemento che stiamo cercando di escludere, nell'elemento della direttiva. Angular applicherà $ scope sull'elemento clone in modo da poter fare tutta la bontà angolare all'interno di quell'elemento.

+7

Vale la pena notare che questa soluzione è deprecata nelle versioni più recenti di Angular. Nello specifico, l'uso dell'argomento transclude passato nella funzione di compilazione. Il modo "corretto" attualmente accettato per fare ciò sarebbe come sopra, eccetto l'uso dell'argomento transclude nella funzione di collegamento (il quinto argomento passato al collegamento). –

4

di approfondire @ post di Rob ...

Transclusion richiede che angolare crea un elemento che è un clone del contenuto di qualsiasi tag direttiva è/vive ... Se il contenuto è testo, lo avvolgerà in un intervallo.

Questo è quindi ha un elemento DOM per applicare l'ambito a quando viene chiamato $ compilazione.

Quindi, fondamentalmente la funzione di esclusione aggiunge un elemento per lo stesso motivo per cui non è possibile $compile('plain text here {{wee}}').

Ora, puoi fare qualcosa di simile a quello che stai cercando di fare con $interpolate, che ti permette di applicare un scope ai binding in una stringa come "blah {{foo}}" .... ma dal Non sono davvero sicuro di cosa stai cercando di fare, non posso davvero darti un esempio specifico.

+0

che cosa è una transizione? – IamStalker

+0

Boom! È sorprendente per quanto tempo possa trovare una semplice risposta, ma questo pezzo proprio qui lo ha sbloccato per me. "La Transclusione richiede che Angular crei un elemento che è un clone del contenuto di qualsiasi tag su cui la direttiva è/vive ... Se il contenuto è testo, lo avvolgerà in un intervallo." Grazie, signore! –

8

Quello che @Vakey ha risposto è quello che stavo cercando.

Ma, come oggi, la documentazione angolare dice:

La funzione transclude che viene passato alla funzione compile è deprecato, come ad esempio non sa del giusto ambito esterno. Utilizzare la funzione di esclusione che viene passata alla funzione di collegamento.

così ho usato invece il controller (per il momento) e la sua funzione $transclude, come parte dell'esempio indicato sul $compile documentation:

controller: function($scope, $element, $transclude) { 
      var transcludedContent, transclusionScope; 

      $transclude(function(clone, scope) { 
       $element.append(clone); 
       transcludedContent = clone; 
       transclusionScope = scope; 
      }); 
     }, 
+0

Per Angular 2, questo è ora noto come ** Proiezioni **, vedere http://stackoverflow.com/a/42019804/2012945 – edmundo096

Problemi correlati