Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get original transcluded content within angular directive

My goal is to create an editable directive that allows a user to edit HTML of any element to which the attribute is attached (see Plunker: http://plnkr.co/edit/nIrr9Lu0PZN2PdnhQOC6)

This almost works except I can't get the original raw HTML of the transcluded content to initialize the text area. I can get the text of it from clone.text(), but that's missing the HTML tags like <H1>, <div>, etc. so clicking apply with no edits is not idempotent.

The method clone.html() throws an error, 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;
      }         
    }
  }
});

(This question is essentially a wholesale rewrite of the question and code after an earlier attempt to frame the question, Get original transcluded content in Angular directive)

like image 873
prototype Avatar asked Nov 20 '13 16:11

prototype


1 Answers

The $element.innerHTML should contain the original HTML. I am showing that it contains

  <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>
like image 55
Nathaniel Johnson Avatar answered Nov 11 '22 17:11

Nathaniel Johnson