2013-11-20 31 views
21

Il mio obiettivo è quello di creare una direttiva editable che consente a un utente di modificare HTML di qualsiasi elemento a cui è collegato l'attributo (si veda Plunker: http://plnkr.co/edit/nIrr9Lu0PZN2PdnhQOC6)Ottenere contenuti transclusa originale entro direttiva angolare

Questo quasi lavori, ad eccezione Non riesco a ottenere l'originale HTML grezzo del contenuto escluso per inizializzare l'area di testo. Posso ottenere il testo di esso da clone.text(), ma che manca i tag HTML come <H1>, <div>, ecc in modo cliccando applicare senza modifiche non è idempotente.

Procedimento clone.html() genera un errore, Cannot read property 'childNodes' of undefined

app.directive("editable", function($rootScope) { 
    return { 
    restrict: "A", 
    templateUrl: "mytemplate.html", 
    transclude: true, 
    scope: { 
     content: "=editContent" 
    }, 

    controller: function($scope, $element, $compile, $transclude, $sce) { 

     // Initialize the text area with the original transcluded HTML... 
     $transclude(function(clone, scope) { 

     // This almost works but strips out tags like <h1>, <div>, etc. 
     // $scope.editContent = clone.text().trim(); 

     // this works much better per @Emmentaler, tho contains expanded HTML 
     var html = ""; 
     for (var i=0; i<clone.length; i++) { 
      html += clone[i].outerHTML||'';} 
     }); 
     $scope.editContent = html; 

     $scope.onEdit = function() { 
     // HACK? Using jQuery to place compiled content 
     $(".editable-output",$element).html(
      // compiling is necessary to render nested directives 
      $compile($scope.editContent)($rootScope) 
     ); 
     } 

     $scope.showEditor = false; 

     $scope.toggleEditor = function() { 
     $scope.showEditor = !$scope.showEditor; 
     }   
    } 
    } 
}); 

(Questa domanda è essenzialmente una riscrittura all'ingrosso della domanda e codice dopo un tentativo precedente per inquadrare la questione, Get original transcluded content in Angular directive)

+2

'clone' è una raccolta di elementi. Sei stato in grado di ispezionarlo in un debugger? –

+0

Aha! L'iterazione su di essi e l'aggiunta di outerHTML è molto più vicina: 'var text =" "; for (var i = 0; i ' mostra '

Clock

{{time}}

'. In questo esempio, l'orologio non esclude il contenuto, quindi l'effetto netto è lo stesso. Mi chiedo se è possibile ottenere l'HTML originale? – prototype

+1

Ho il sospetto che potrebbe essere il caso. Buon affare. L'HTML originale potrebbe trovarsi nell'oggetto $ elemento nello scope esterno. La Transclusione non è il mio forte seme. –

risposta

3

Il $element.innerHTML dovrebbe contenere l'HTML originale Sto mostrando che contiene

<div class="editable"> 
    <span class="glyphicon glyphicon-edit" ng-click="toggleEditor()"></span> 

    <div class="editable-input" ng-show="showEditor"> 
     <b><p>Enter well-formed HTML content:</p></b> 
     <p>E.g.<code>&lt;h1&gt;Hello&lt;/h1&gt;&lt;p&gt;some text&lt;/p&gt;&lt;clock&gt;&lt;/clock&gt;</code></p> 
     <textarea ng-model="editContent"></textarea> 
     <button class="btn btn-primary" ng-click="onEdit()">apply</button> 
    </div> 

    <div class="editable-output" ng-transclude=""></div> 
    </div> 
+3

Molto utile. Questo contiene il testo del modello. La tua risposta mi ha spinto ad aggiungere il metodo 'compile (elemento, attrs)' che ha l'HTML transcluso nel suo 'innerHTML'. Ma è dopo che Angular lo ha espanso in nuovi elementi DOM usando il modello. Questo si interromperà se alcuni elementi secondari hanno 'replace: true' o non si escludono i contenuti stessi. Sospetto che non sia possibile ottenere che Angular fornisca l'HTML da prima che Angular lo elaborasse, e quindi il contenuto di partenza dovrebbe essere riavviato non tramite la transclusione ma passato attraverso un attributo o ajax. – prototype

+0

Questo entra nelle viscere del ciclo di digestione. Impostando la priorità arbitrariamente alta, potresti essere in grado di assicurarti che venga valutata per prima. –

+0

Come ottenere il contenuto di inclusione non compilato di una direttiva Angolare se utilizzo 'replace: true' con template. significa 'elemento' non contiene il contenuto originale grezzo perché l'elemento 'element' non è un elemento originale –

Problemi correlati