是否有可能编译角模板,最终的HTML字符串? [英] Is it possible to compile angular template to final html string?

查看:257
本文介绍了是否有可能编译角模板,最终的HTML字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能编译这个HTML模板字符串:

 < P>从产品列表{{supplier.name}}< / P>
< p NG重复=裁判在裁判> {{REF}}< / P>中

直接到HTML字符串,如:

 < P>从一些供应商和LT的产品目录; / P>
&所述p为H.; a0120&下; / P>
&所述p为H.; a0241&下; / P>
&所述p为H.; z1242&下; / P>
&所述p为H.; z3412&下; / P>中

或者至少少干净的版本:

 < p =类NG-NG范围结合>从杜瓦尔&LT产品清单; / P>
< - ngRepeat:裁判在裁判轨道由$指数 - >
< p NG重复=裁判在裁判轨道由$指数级=NG-NG范围结合> a0120< / P>
< p NG重复=裁判在裁判轨道由$指数级=NG-NG范围结合> a0241< / P>
< p NG重复=裁判在裁判轨道由$指数级=NG-NG范围结合> z1242< / P>
< p NG重复=裁判在裁判轨道由$指数级=NG-NG范围结合> z3412< / P>中

我试着使用$编译(templateStr)($范围内),但返回的未完全处理的DOM元素。
不过,我没有管理的使用下面的指令,并和检查该元素编译到一个页面元素,我可以看到它有我在寻找最终的HTML:

  app.directive('编译',函数($编译){
    返回{
        限制:'A',
        范围: {
            编译:'=编译,
            数据:'= ngData
        },
        链接:功能(范围,元素,ATTRS){
            范围。$表(数据,
                    功能(值){
                        对(在scope.data变种K)
                            范围[K] = scope.data [K];
                    }
            )            范围。$腕表('编译',
                    功能(值){
                        element.html(值);
                        风险价值= $编译(element.contents())(范围);
                    }
            )
        }
    }
})

有什么办法,我可以直接从模板中得到最终的HTML?
谢谢

PS:
我想在这里实现的是直接的CKEditor编辑模板(在文本模式下,而不是源)
只有最终goint源模式添加一些NG重复属性。
喜欢把手使用模板引擎需要的HTML元素外占位符和CKEditor的是automaticaly被删除,因为它只能与HTML交易。

可能的解决方案(哈克):
一种可能的方法是使用一个隐藏的元素上的编译指令和读元素的含量视图被加载控制器上后:


  $ $范围在('$ viewContentLoaded',$ scope.onLoaded)。
$超时(函数(){
    VAR EL = $(#DIV文)[0]
    cleanAngularStuff(EL)
    $ scope.currMailTemplate.processed = el.innerHTML
});


该cleanAngularStuff功能只是清洁额外的角度指令和类。

我会后的here如果有人想使用它或改善它。

什么更好的办法来做到这一点无需添加元素的网页?


解决方案

您需要做的就是访问编译元素$消化后循环什么。

所以内$消化周期可以这样做:

  templateString ='<有的-模板 -  code />';
...
VAR编译= $编译(templateString)(范围);
//范围。$ //消化仅在调用这个不是内$消化周期//你可以做一个$超时让previous消化周期完成
$超时(函数(){
  VAR theHtml =编译[0] .outerHTML;
  的console.log(,theHtml'与变量的HTML');
});

如果您还不是消化周期内,那么你需要手动调用范围。$摘要()。你可以看到下面的嵌入式样本。

\r
\r

(函数(){\r
  使用严格的;\r
  VAR应用= angular.module('soApp',[]);\r
  \r
  app.directive('showCompiledTemplate',[\r
            '$编译,$超时',\r
    功能(编译$,$超时){\r
      返回{\r
        限制:'E',\r
        模板:'< D​​IV CLASS =编译模板>' +\r
'< D​​IV>< textarea的COLS =40行=15只读>< / textarea的>< / DIV>' +\r
          '< D​​IV CLASS =输出>< / DIV>' +\r
                  '< / DIV>,\r
        范围: {\r
          数据:=,\r
          模板:'='\r
        },\r
        链接:功能(范围,ELEM,ATTRS){\r
            变种的textarea = elem.find('文本区域')[0];\r
            。无功输出= elem.children()儿童()方程(1);\r
VAR updateOutput =功能(TPL){\r
                VAR编译= $编译(TPL)(范围);\r
                $超时(函数(){\r
                    VAR theHtml =编译[0] .outerHTML;\r
                    textarea.value = theHtml;\r
                    output.html(theHtml);\r
                });\r
            };\r
            范围。$表(模板功能(TPL){\r
updateOutput(TPL);\r
            });\r
            范围。$表(数据功能(){\r
                updateOutput(scope.template);\r
            },真正);\r
        }\r
      };\r
    }\r
  ]);\r
  \r
  app.controller('MainCtrl',函数(){\r
    this.data = {\r
      名称:'约翰',\r
      清单:一鸭,两只鸭子,三只鸭子']\r
    };\r
    //this.template =< D​​IV>喜< / DIV>中;\r
    VAR模板='';\r
    模板+ ='< D​​IV> \\ n';\r
    模板+ ='< P> {{data.name}}< / P> \\ n';\r
    模板+ ='< UL> \\ n';\r
    模板+ ='<李NG重复=,在Data.List模块项目> {{}项}< /李> \\ n';\r
    模板+ ='< / UL> \\ n';\r
    模板+ ='< / DIV> \\ n';\r
    this.template =模板;\r
  });\r
  \r
 })();

\r

.FORM场{\r
    填充底:10px的;\r
}\r
.FORM场跨度{\r
    宽度:70像素;\r
    显示:inline-block的;\r
}\r
.compiled模板{\r
   显示:-webkit-FLEX;\r
   显示:弯曲;\r
   -webkit-FLEX方向:排;\r
   柔性方向:排;\r
}\r
.compiled模板的textarea {\r
    背景色:#eee;\r
    保证金权:10px的;\r
}\r
.compiled模板.OUTPUT {\r
    边框:1px的固体#CCC;\r
    填充:10px的;\r
}

\r

&LT;脚本SRC =htt​​ps://cdnjs.cloudflare.com/ajax /libs/angular.js/1.4.6/angular.js\"></script>\r
&LT; D​​IV NG-应用=soApp&GT;\r
  &LT; D​​IV NG控制器=MainCtrl为主&GT;\r
      &LT; D​​IV CLASS =表单域&GT;\r
          &LT;跨度类=形式的标签&GT;名称:LT; / SPAN&GT;\r
          &LT;输入类型=文本NG模型=main.data.name/&GT; &LT; BR /&GT;\r
      &LT; / DIV&GT;\r
      &LT; D​​IV CLASS =表单域&GT;\r
          &LT;跨度类=形式的标签&GT;模板:&LT; / SPAN&GT;\r
          &LT; textarea的NG-模式=main.templateCOLS =40行=8&GT;&LT; / textarea的&GT; &LT; BR /&GT;\r
      &LT; / DIV&GT;\r
      &LT; D​​IV&GT;\r
          &LT;显示编译模板数据=main.data模板=main.template/&GT;\r
      &LT; D​​IV&GT;\r
  &LT; / DIV&GT;\r
&LT; / DIV&GT;

\r

\r
\r

Is it possible to compile this html template string:

"<p>List of products from {{supplier.name}}</p>
<p ng-repeat="ref in refs">{{ref}}</p>"

directly to an html string like:

"<p>List of products from Some Supplier</p>
<p>a0120</p>
<p>a0241</p>
<p>z1242</p>
<p>z3412</p>"

or at least the less clean version:

"<p class="ng-scope ng-binding">List of product from Duval</p>
<!-- ngRepeat: ref in refs track by $index -->
<p ng-repeat="ref in refs track by $index" class="ng-scope ng-binding">a0120</p>
<p ng-repeat="ref in refs track by $index" class="ng-scope ng-binding">a0241</p>
<p ng-repeat="ref in refs track by $index" class="ng-scope ng-binding">z1242</p>
<p ng-repeat="ref in refs track by $index" class="ng-scope ng-binding">z3412</p>"

I tried using $compile(templateStr)($scope) but the dom elements returned are not fully processed. However I managed no compile it to a page element using the following directive and and inspecting that element I can see it has the final html I'm looking for:

app.directive('compile', function($compile) {
    return{
        restrict: 'A',
        scope: {
            compile: '=compile',
            data: '=ngData'
        },
        link: function(scope, element, attrs) {
            scope.$watch('data',
                    function(value) {
                        for (var k in scope.data)
                            scope[k] = scope.data[k];
                    }
            )

            scope.$watch('compile',
                    function(value) {
                        element.html(value);
                        var a = $compile(element.contents())(scope);
                    }
            )
        }
    }
})

Is there any way I can get that final html directly from the template? Thanks

PS: What I'm trying to achieve here is to edit a template directly in CKEditor (in text mode, not source) and only eventually goint to source mode to add some "ng-repeat" attributes. Using template engines like Handlebars require placeholders outside html elements and are automaticaly erased by CKEditor since it only deals with html.

POSSIBLE SOLUTION (hacky): One possible way is to use the compile directive on an hidden element and read the element's content after view is loaded on the controller:

$scope.$on('$viewContentLoaded', $scope.onLoaded);
$timeout(function() {
    var el =$("#text div")[0]
    cleanAngularStuff(el)
    $scope.currMailTemplate.processed = el.innerHTML
});

The cleanAngularStuff function is just to clean extra angular directives and classes.

I'll post it here if someone wants to use it or improve it.

Any better way to do this without adding an element to the page?

解决方案

What you need to do is access the compiled element after a $digest cycle.

So within a $digest cycle you can do:

templateString = '<some-template-code/>';
...
var compiled = $compile(templateString)(scope);
// scope.$digest // only call this if not within a $digest cycle

// you can do a $timeout to let the previous digest cycle complete
$timeout(function(){
  var theHtml = compiled[0].outerHTML;
  console.log('the html with the variables', theHtml);
});

If you aren't already within a digest cycle then you need to manually call scope.$digest(). You can see the embedded sample below.

(function(){
  "use strict";
  var app = angular.module('soApp', []);
  
  app.directive('showCompiledTemplate',[
            '$compile','$timeout',
    function($compile , $timeout) {
      return {
        restrict: 'E',
        template: '<div class="compiled-template">' +
			        '<div><textarea cols="40" rows="15" readonly></textarea></div>' +
          			'<div class="output"></div>' +
                  '</div>',
        scope: {
          data: '=',
          template: '='
        },
        link: function(scope,elem,attrs) {
            var textarea = elem.find('textarea')[0];
            var output = elem.children().children().eq(1);
			var updateOutput = function(tpl) {
                var compiled = $compile(tpl)(scope);
                $timeout(function(){
                    var theHtml = compiled[0].outerHTML;
                    textarea.value = theHtml;
                    output.html(theHtml);
                });
            };
            scope.$watch("template",function(tpl){
				updateOutput(tpl);
            });
            scope.$watch("data",function(){
                updateOutput(scope.template);
            },true);
        }
      };
    }
  ]);
  
  app.controller('MainCtrl', function() {
    this.data = {
      name: 'John',
      list: ['one duck','two ducks','three ducks']
    };
    //this.template = "<div>hi</div>";
    var template = '';
    template += '<div>\n';
    template += '  <p>{{data.name}}</p>\n';
    template += '  <ul>\n';
    template += '    <li ng-repeat="item in data.list">{{item}}</li>\n';
    template += '  </ul>\n';
    template += '</div>\n';
    this.template = template;
  });
  
 })();

.form-field {
    padding-bottom: 10px;
}
.form-field span {
    width: 70px;
    display: inline-block;
}
.compiled-template {
   display: -webkit-flex;
   display: flex;
   -webkit-flex-direction: row;
   flex-direction: row;
}
.compiled-template textarea {
    background-color: #eee;
    margin-right: 10px;
}
.compiled-template .output {
    border: 1px solid #ccc;
    padding: 10px;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.6/angular.js"></script>
<div ng-app="soApp">
  <div ng-controller="MainCtrl as main">
      <div class="form-field">
          <span class="form-label">Name:</span>
          <input type="text" ng-model="main.data.name" /> <br/>
      </div>
      <div class="form-field">
          <span class="form-label">Template:</span>
          <textarea ng-model="main.template" cols="40" rows="8"></textarea> <br/>
      </div>
      <div>
          <show-compiled-template data="main.data" template="main.template" />
      <div>
  </div>
</div>

这篇关于是否有可能编译角模板,最终的HTML字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆