如何使 ng-bind-html 编译 angularjs 代码

Posted

技术标签:

【中文标题】如何使 ng-bind-html 编译 angularjs 代码【英文标题】:How to make ng-bind-html compile angularjs code 【发布时间】:2013-11-12 14:52:01 【问题描述】:

我正在使用 angularjs 1.2.0-rc.3。我想将 html 代码动态地包含到模板中。为此我在控制器中使用:

html = "<div>hello</div>";
$scope.unicTabContent = $sce.trustAsHtml(html);

在我得到的模板中:

<div id="unicTab" ng-bind-html="unicTabContent"></div>

它适用于常规 html 代码。但是当我尝试放置角度模板时,它不会被解释,它只是包含在页面中。例如,我想包括:

<div ng-controller="formCtrl">
    <div ng-repeat="item in content" ng-init="init()">
    </div>
</div>

非常感谢

【问题讨论】:

是的,这并不是 Angular 想要的工作方式。如果要动态添加 html,请查看 $complie 服务。 为什么不使用ngScript创建about模板,然后使用ng-include,ng-src添加它 【参考方案1】:

一种方法是使用指令来插入包含角度表达式的自定义模板

<div id="unicTab" unic-tab-content></div>
app.directive("unicTabContent",function()
   return 
      restrict:"A",
      template:'unicTabContent'
   
)

【讨论】:

我喜欢这个想法,它确实包含了代码,但仍然没有编译。 和plnkr.co/edit/sUOxHBUYIdQlAiM3Dy0V?p=preview 一样在这里工作得很好,也许你有一些嵌套指令或其他导致它不起作用的东西 但我希望它能够编译您调用 test.xml 的变量中的代码。例如plunker 显示 和 ,这不是我想要的。 OK..可以用link指令回调Plunker来做到这一点 确实可以编译 html,但不能编译 angular 语句。在Plunker 中,当直接注入测试变量时,ng-click 方法已连接,但使用指令注入时则没有。【参考方案2】:

正如 Vinod Louis 在他的评论中所说,最好的方法是使用模板。我必须在常规代码之外定义一个模板,例如我在 index.html 中添加了该代码:

<script type="text/ng-template" id="unic_tab_template.html">
    <div ng-switch on="page">
        <div ng-switch-when="home"><p>home</p></div>
        <div ng-switch-when="form">
            <div ng-controller="formCtrl">
                <div ng-repeat="item in content">item.name:item.value</div>
            </div>
        </div>
        <div ng-switch-default>an error accured</div>
    </div>
</script>

此模板是有条件的,因此根据 $scope.page 的值,它会在 3 个模板之间切换(第三个是错误处理程序)。要使用它,我有:

<div id="unicTab" ng-controller="unicTabCtrl">
    <div ng-include="'unic_tab_template.html'"></div>
</div>

这样我的页面会根据我的 unicTabCtrl 控制器中的 $scope 而改变。

总结一下很难实现插入 angularsjs 模板接缝的想法($compile seams 是解决方案,但我无法使其工作)。但您可以改为使用条件模板。

【讨论】:

我喜欢这个解决方案,但是如果我们能看到一个 HTML 来自其他地方的示例会更好(例如远程 JSON,因此在项目中没有硬编码)。跨度> 【参考方案3】:

我试图做同样的事情并遇到了这个模块。

http://ngmodules.org/modules/ng-html-compile

我只是包含它,然后我就可以使用“ng-html-compile”而不是“ng-bind-html”

【讨论】:

【参考方案4】:

此解决方案不使用硬编码模板,您可以编译嵌入在 API 响应中的 Angular 表达式。


第 1 步。 安装此指令:https://github.com/incuna/angular-bind-html-compile

第 2 步。 在模块中包含指令。

angular.module("app", ["angular-bind-html-compile"])

第 3 步。 使用模板中的指令:

<div bind-html-compile="letterTemplate.content"></div>

结果:

控制器对象

 $scope.letter =  user:  name: "John"

JSON 响应

 "letterTemplate":[
     content: "<span>Dear letter.user.name,</span>" 
]

HTML 输出 =

<div bind-html-compile="letterTemplate.content"> 
   <span>Dear John,</span>
</div>

为了参考,下面是相关指令:

(function () 
    'use strict';

    var module = angular.module('angular-bind-html-compile', []);

    module.directive('bindHtmlCompile', ['$compile', function ($compile) 
        return 
            restrict: 'A',
            link: function (scope, element, attrs) 
                scope.$watch(function () 
                    return scope.$eval(attrs.bindHtmlCompile);
                , function (value) 
                    element.html(value);
                    $compile(element.contents())(scope);
                );
            
        ;
    ]);
());

【讨论】:

这个 jsfiddle 有助于说明 ng-bind-htmlbind-html-compile 之间的编译差异:jsfiddle.net/HB7LU/14557 我想在我意识到这将如何简单地解决我的问题之前,我曾三次问过这个问题。如果可以的话,我会投票两次。【参考方案5】:

我在不使用模板的情况下在当前应用程序中解决类似问题(不优雅,但有效):

directive('ngBindHtmlCompile', ['$compile', function ($compile) 
    return 
        restrict: 'A',
        compile: function compile(tElement, tAttributes, transcludeFn) 
            return function postLink(scope, element, attributes) 
                scope.$watch(function() 
                    return scope.$eval(attributes.ngBindHtml);
                , function(newValue, oldValue) 
                    $compile(element.children())(scope);
                );
            ;
        
    ;
]);

它需要ngBindHtml在同一个元素上,并在元素内容更改为ngBindHtml后编译。

<div id="unicTab" ng-bind-html="unicTabContent" ng-bind-html-compile></div>

ng-html-compile 看起来很相似,但乍一看它不会在模板内容发生变化时重新计算。但我没试过。

【讨论】:

【参考方案6】:

这是我做的,不知道是不是角度的方式TM,但它工作并且超级简单;

.directive('dynamic', function($compile) 
    return 
        restrict: 'A',
        replace: true,
        link: function (scope, element, attrs) 
            scope.$watch(attrs.dynamic, function(html) 
                $compile(element.html(html).contents())(scope);
            );
        
    ;
);

所以;

<div id="unicTab" dynamic="unicTabContent"></div>

编辑:我找到了角度方式,它超级简单。

$templateCache.put('unicTabContent', $sce.trustAsHtml(html));
<div id="unicTab" ng-include="'unicTabContent'"></div>

不需要制定自己的指令或任何东西。 但这是一种绑定一次的交易,it wont see changes made to your html 就像 the custom directive does。

【讨论】:

我发现这个答案是最容易实现的。 嘿,为什么在这里使用 $watch?为什么不直接用编译后的内容替换元素呢?谢谢顺便说一句。 这样如果变量发生变化,该变化将反映在下一个digest 的DOM 中。如果你的变量永远不会改变,你可以简化这一点,当然,但每当我提出答案时,我都会尽量保持它的通用性和普遍适用性。对于我的具体情况,我认为当指令被评估时我的变量是空的,所以我需要 watch 来表示变量最终被填充的时候。 这对我来说效果更好!特别是如果您也使用带有元素的过滤器,那么这绝对是要走的路。如果使用 angular-bind -html-compile 东西,我会达到摘要限制 有什么方法可以使 ng-html-compile 有条件?我的意思是仅在特定条件下附加/分配指令,例如 - 网格行单击并正常运行?【参考方案7】:

使用 Angular 内置的 $interpolate 和 $sce 对象,下面的代码要简单得多。首先将 $interpolate 和 $sce Angular 对象注入到您的指令中,就像您在指令中执行任何您需要的自定义操作一样。

amqApp.directive('myDir', ['$interpolate', '$sce', function ($interpolate,$sce ) ...

然后创建在导入的 html 表达式中找到的所有作用域变量...

$scope.custom = 'Hello World';

接下来使用 $interpolate 处理您的自定义 HTML 及其表达式...然后确保在绑定之前使用 $sce 对象将其信任为 HTML...

var html = $interpolate('<b>custom</b>')($scope);    
$scope.data = $sce.trustAsHtml(html);

最后,在您的视图中,只需确保在视图显示中使用带有“ng-bind”或“ng-bind-html”的元素。我发现 $sce 片段不会将 HTML 显示为 HTML(将其视为文本),如果您不将它绑定到这样的 html 模板中...

<span ng-bind-html="data"></span>

你应该看到粗体...

你好世界

我使用这个技巧从 web.config 导入带有自定义角度 expressions 的文本/HTML。

【讨论】:

【参考方案8】:

@clement-roblot 基于内置模板的大量简化解决方案。

控制器:

app.controller('TestCtrl', [
    '$scope',
    '$templateCache',
    function ($scope, $templateCache) 
        $templateCache.put('test.html', '2 + 2 =  2 + 2 ');
    
]);

查看:

<div ng-include="'test.html'"></div>

【讨论】:

以上是关于如何使 ng-bind-html 编译 angularjs 代码的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS 2 中如何实现ng-bind-html

如何使用 ng-bind-html 插入 Angular 1.5 组件

使用 ng-bind-html 来自 Angular Array 的 iframe 视频

angularjs ng-bind-html的用法总结

ng-bind-html 元素不适用于音频标签

ng-bind-html指令和$sce服务