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: )
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, $pile, $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 piled content
$(".editable-output",$element).html(
// piling is necessary to render nested directives
$pile($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)
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, $pile, $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 piled content
$(".editable-output",$element).html(
// piling is necessary to render nested directives
$pile($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)
javascript
angularjs
transclusion
Share
Improve this question
edited May 23, 2017 at 10:31
CommunityBot111 silver badge
asked Nov 20, 2013 at 16:56
prototypeprototype8,0051515 gold badges6767 silver badges100100 bronze badges7
2clone is a collection of elements. Have you been able to inspect it in a debugger?
– Nathaniel Johnson
CommentedNov 20, 2013 at 17:22
Aha! Iterating over them and appending outerHTML is much closer: var text = ""; for (var i=0; i<clone.length; i++) {text += clone[i].outerHTML||'';}. However, one remaining gap is the HTML of the nested directives is expanded, e.g. instead of just <clock></clock> it shows <clock><span class="clock"><div class="btn btn-success"><h1>Clock</h1><p>{{time}}</p></div></span></clock>. In this example, the clock doesn't transclude content, so the net effect is the same. I wonder if it's possible to get the original HTML?
– prototype
CommentedNov 20, 2013 at 17:48
1I suspected it might be the case. Good deal. The original HTML might be sitting in the $element object in the outer scope. Transclusion is not my strong suit.
– Nathaniel Johnson
CommentedNov 20, 2013 at 17:57
why aren't you wrapping original content in an element with a class that you can use to find it and keep it isolated in one container?
– charlietfl
CommentedNov 20, 2013 at 18:34
1if it was me would just add textarea/editor on demand like with doubleclcik. Append when needed.
– charlietfl
CommentedNov 20, 2013 at 18:45
|
Show 2 more ments
1 Answer
1
Reset to default
3
The $element.innerHTML should contain the original HTML. I am showing that it contains