在角度指令中获取原始嵌入内容
Posted
技术标签:
【中文标题】在角度指令中获取原始嵌入内容【英文标题】:Get original transcluded content within angular directive 【发布时间】:2013-12-04 19:21:49 【问题描述】:我的目标是创建一个editable
指令,允许用户编辑附加属性的任何元素的 html(请参阅 Plunker:http://plnkr.co/edit/nIrr9Lu0PZN2PdnhQOC6)
这个几乎可以工作,只是我无法获得嵌入内容的原始原始 HTML 来初始化文本区域。我可以从clone.text()
获取它的文本,但是缺少像<H1>
、<div>
等HTML 标签,所以点击应用而不进行编辑不是幂等的。
clone.html()
方法抛出错误,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;
);
(这个问题本质上是在较早尝试构建问题之后对问题和代码的全面重写,Get original transcluded content in Angular directive)
【问题讨论】:
clone
是元素的集合。您是否能够在调试器中对其进行检查?
啊哈!遍历它们并附加 outerHTML 更接近:var text = ""; for (var i=0; i<clone.length; i++) text += clone[i].outerHTML||'';
。但是,剩下的一个差距是嵌套指令的 HTML 被扩展,例如而不仅仅是<clock></clock>
,它显示<clock><span class="clock"><div class="btn btn-success"><h1>Clock</h1><p>time</p></div></span></clock>
。在此示例中,时钟不包含内容,因此最终效果是相同的。我想知道是否有可能得到原始的HTML?
我怀疑可能是这种情况。很好的交易。原始 HTML 可能位于外部范围的 $element 对象中。嵌入不是我的强项。
为什么不将原始内容包装在一个元素中,并使用一个类来查找它并将其隔离在一个容器中?
如果是我,只需像使用 doubleclcik 一样按需添加 textarea/editor。需要时追加。
【参考方案1】:
$element.innerHTML
应包含原始 HTML。我表明它包含
<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><h1>Hello</h1><p>some text</p><clock></clock></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>
【讨论】:
非常有帮助。包含模板文本。您的回答确实激发了我添加compile(element, attrs)
的方法,该方法在其 innerHTML
中包含嵌入的 HTML。但这是在 Angular 使用模板将其扩展为新的 DOM 元素之后。如果任何子元素具有 replace:true
或本身包含内容,那将会中断。我怀疑在 Angular 处理它之前没有办法让 Angular 提供 HTML,因此需要引导起始内容而不是通过嵌入,而是通过属性或 ajax 传递。
这进入了摘要循环的核心。通过将优先级设置为任意高,您也许可以确保首先对其进行评估。
如果我将replace:true
与模板一起使用,如何获取 Angular 指令的未编译嵌入内容。这意味着element
不包含原始原始内容,因为element
是模板元素而不是原始元素以上是关于在角度指令中获取原始嵌入内容的主要内容,如果未能解决你的问题,请参考以下文章