将 html 内容附加到 Angular JS 中的 iframe

Posted

技术标签:

【中文标题】将 html 内容附加到 Angular JS 中的 iframe【英文标题】:Append html content to an iframe in Angular JS 【发布时间】:2014-03-29 15:41:23 【问题描述】:

我正在尝试创建一个完整的 html 文档的预览,这意味着这个 html 内容本身就是一个带有<html><head><body> 标签的完整 html 文档。

如果我只是将该 html 文档加载到我现有的 html 根目录中,那么所有样式都将被新包含的 html 文档中定义的样式覆盖。如果我在 src (<ifram e src="path/to/doc.html">) 上包含这个带有 iframe 的 html 文档,那么它就可以工作。但是,这个 doc.html 是一个模板,我需要在其中替换我用自定义标签注释的某些部分。我通过执行以下代码来做到这一点

$.get('template/template.html', function (template) 

    String.prototype.format = function () 
        var args = arguments;
        this.unkeyed_index = 0;
        return this.replace(/\(\w*)\/g, function (match, key) 
            if (key === '') 
                key = this.unkeyed_index;
                this.unkeyed_index++
            
            if (key == +key) 
                return args[key] !== 'undefined'
                    ? args[key]
                    : match;
             else 
                for (var i = 0; i < args.length; i++) 
                    if (typeof args[i] === 'object' && typeof args[i][key] !== 'undefined') 
                        return args[i][key];
                    
                
                return match;
            
        .bind(this));
    ;

    var renderedHtml = template.format(hello: "hey there");
);

到目前为止,这工作正常。在变量 renderedHtml 中,我有完整的 html 文档,并且占位符正在被替换(在这种情况下,占位符 hello 被替换为“hey there”。

不,我有以下 html sn-p

<iframe id="test"></iframe>

我尝试了以下代码:

  var elem = document.createElement('div');
  elem.innerHTML = renderedHtml;
  document.getElementById('test').appendChild(elem);
  $compile(elem)($scope);

不幸的是,视图没有任何变化。但是,如果我在document.body 上调用appendChild(elem),那么它可以工作。有谁知道可能是什么问题?

附:我知道你不应该在你的角度控制器中做 DOM 操作,而不是 $compile 你应该用一个指令来做。但是,如果这种方式可行,那么我很乐意尝试将其重构为指令:)。

【问题讨论】:

【参考方案1】:

我不得不做一些类似于你正在做的事情。我需要为一些 HTML 模板制作一个编辑器。由于现有网站中的 CSS,模板没有很好地预览,所以我想在 iframe 中显示模板。

我能够制作一个带有手表的角度指令,它会更新:iframe.contentDocument.body.innerHTML 并得到我想要的效果。我相信您将能够截取此处的内容,并对模板中的占位符进行任何替换。

下面的 preview 指令应该可以帮助您,如果您在这段时间之后仍然需要它。

var app = angular.module('App',[]);

app.controller("Cont", function($scope)
  $scope.content = "Hi there!";
);

app.directive("preview", function () 
  function link(scope, element) 
    var iframe = document.createElement('iframe');
    var element0 = element[0];
    element0.appendChild(iframe);
    var body = iframe.contentDocument.body;

    scope.$watch('content', function () 
      body.innerHTML = scope.content;
    );
  

  return 
    link: link,
    restrict: 'E',
    scope: 
      content: '='
    
  ;
);
input, iframe 
  border: solid 1px black;
  width: 100px;

preview iframe 
  height: 50px;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="App" ng-controller="Cont">
  <input ng-model="content" type="text" /><br />
  <preview content="content"></preview>
</div>

【讨论】:

为什么指令中需要这段代码** content: '=' ** 虽然是一个(相对)旧的解决方案,但我在我的应用程序中很好地使用了它来在 iframe 中显示模板渲染的内容。但是,我刚刚开始在 FireFox 中查看这个,我只是得到一个空白的 iFrame。任何想法为什么会这样? @BrendanGreen 查看我基于 Chris 的解决方案,该解决方案也适用于 firefox【参考方案2】:

基于 Chris 针对 Firefox 浏览器问题的人的解决方案的更新解决方案:

var app = angular.module('App',[]);

app.controller("Cont", function($scope)
  $scope.content = "Hi there!";
);

app.directive("preview", function () 
  function link(scope, element) 
    var iframe = document.createElement('iframe');
    var element0 = element[0];
    element0.appendChild(iframe);

    scope.$watch('content', function () 
      iframe.contentWindow.document.open('text/htmlreplace');
      iframe.contentWindow.document.write(scope.content);
      iframe.contentWindow.document.close();
    );
  

  return 
    link: link,
    restrict: 'E',
    scope: 
      content: '='
    
  ;
);

【讨论】:

以上是关于将 html 内容附加到 Angular JS 中的 iframe的主要内容,如果未能解决你的问题,请参考以下文章

如何使用innerHTML在angular 2中附加HTML内容

Angular JS - 单击按钮从指令加载模板 html

Angular 2 将组件动态附加到 DOM 或模板

用于附加侧边栏的 Angular 指令

将内容附加到列表时保持滚动位置(AngularJS)

使用javascript函数将复杂的HTML附加到div?