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

时间:2014-02-26 16:42:34

标签: jquery angularjs dom iframe

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

如果我只是将该html文档加载到我现有的html根目录中,那么所有样式都将被新包含的html doc中定义的样式覆盖。如果我将这个带有iframe的html文档包含在src(<ifram e src="path/to/doc.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文档,占位符正在被替换(在这种情况下,占位符问候语被替换为“嘿那里”。

不,我有以下html代码段

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

我尝试了以下代码:

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

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

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

2 个答案:

答案 0 :(得分:9)

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

我能够制作一个带有手表的角度指令,它会更新:iframe.contentDocument.body.innerHTML并获得我想要的效果。我相信您可以在此拦截内容,并在模板中替换占位符。

下面的预览指令可以帮助您,如果您在此之后仍然需要它。

&#13;
&#13;
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: '='
    }
  };
});
&#13;
input, iframe {
  border: solid 1px black;
  width: 100px;
}
preview iframe {
  height: 50px;
}
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

基于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: '='
    }
  };
});