简体   繁体   English

将角度模板编译成html的正确方法,将结果转换为字符串

[英]A proper way to compile angular template into html, convert result into string

Abstract 抽象

Hi, I'm using angular to render documents, I have the view-model that contains the data which should go into document, and I have angular template that represents the document. 嗨,我使用角度渲染文档,我有视图模型,其中包含应该进入文档的数据,我有角度模板,代表文档。 The template is valid angular-html markup that is later rendered using angular's $compile , here is directive I use to render documents for presentation purposes: 该模板是有效的angular-html标记,稍后使用angular的$ compile进行渲染,这是我用于呈现文档的指令:

angular.module('app').directive('render', function ($compile, server) {
    return {
        restrict: 'E',
        link: function ($scope, $element, $attributes) {
            var scope;

            server.resolve().then(function (repo) {
                var _template, _constants, _variables, _substitutes;

                var render = function () {
                    if (_template) {
                        $scope.repo = repo;

                        var references = repo.references;

                        if (_constants) {
                            for (var constantName in _constants) {
                                $scope[constantName] = references[_constants[constantName]];
                            }
                        }

                        if (_variables) {
                            for (var variableName in _variables) {
                                var substitute = _substitutes[variableName];
                                var variableValue = _variables[variableName];

                                var reference = repo.references[substitute];

                                if (reference) {
                                    if (reference.table === variableValue) {
                                        $scope[variableName] = reference;
                                    } else {
                                        throw new Error('Invalid reference type');
                                    }
                                }
                            }
                        }

                        if (scope) scope.$destroy();

                        scope = $scope.$new();

                        var element = angular.element('<div class="print"></div>');
                        element.html(_template);

                        $element.empty();
                        $element.append(element);

                        $compile(element)(scope);
                    }

                };

                $scope.$watch($attributes.template, function (template) {
                    _template = template;
                    render();
                });

                $scope.$watch($attributes.constants, function (constants) {
                    _constants = constants;
                    render();
                });

                $scope.$watch($attributes.variables, function (variables) {
                    _variables = variables;
                    render();
                });

                $scope.$watchCollection($attributes.substitutes, function (substitutes) {
                    _substitutes = substitutes;
                    render();
                });
            });
        }
    };
});

Question

I need to make a hard-copy of the document, in other words I need to substitute the view-model values into document template, convert result into string and put it into variable. 我需要制作文档的硬拷贝,换句话说,我需要将视图模型值替换为文档模板,将结果转换为字符串并将其放入变量中。 I can't use directive for that, angular's $compile is really heavy function to call, it creates watches under the hood, I don't need whole shebang, I just need to substitute values. 我不能使用指令,angular的$ compile实际上是很重要的函数调用,它创建了引擎盖下的手表,我不需要整个shebang,我只需要替换值。 What would be the best way to do that? 最好的方法是什么?

Thank you in advance 先感谢您

With your tip for $interpolate I could finalize my demo for your question. 有了$interpolate的提示,我可以为你的问题完成我的演示。

It's with-out a service for storing the interpolated template into database to keep the demo focused on the issue. 它没有用于将插值模板存储到数据库中的服务,以使演示集中在该问题上。

So as I've understood, the difference between $compile and $interpolate is the following: 正如我所理解的, $compile$interpolate之间的区别如下:

  • $compile : Creates DOM elements with angular binding to scope. $compile :使用与范围的角度绑定创建DOM元素。 That's what you would normally use to render your DOM to have two-way binding etc. working. 这就是您通常用于渲染DOM以使双向绑定等工作的内容。 In most cases you don't call it manually because if you add template or templateUrl to the direcive definition object it will run $compile automatically. 在大多数情况下,您不会手动调用它,因为如果将templatetemplateUrl添加到direcive定义对象,它将自动运行$compile

  • $interpolate : It is pretty similar to compile with the only difference that it will return the DOM elements wiht-out angular bindings. $interpolate :它与编译非常相似,唯一的区别是它将返回带有角度绑定的DOM元素。

You can see the difference if you have a look at the rendered html markup. 如果你看一下渲染的html标记,你可以看到差异。 Compiled templates have ng-binding class in the markup and the other is just static html with-out that class. 编译模板在标记中有ng-binding类,另一个只是静态html而没有该类。

So as you mentioned $interpolate is the way to go to get the compiled string that you can easily store in the database with a $http service. 因此,正如您所提到的, $interpolate是获取编译字符串的方法,您可以使用$http服务轻松存储在数据库中。

Please have a look at the demo below or at this jsfiddle . 请看下面的演示或这个jsfiddle

 angular.module('myApp', []) .directive('render', Render); var templateStore = []; function Render($compile, $interpolate) { return { restrict: 'E', controllerAs: 'render', controller: function () { this.hello = 'hello from controller'; //console.log($templateCache.get('testTemplate')); }, compile: function (tElem, tAttrs) { return function (scope, element, attrs, controllers) { //controllers.hello = 'hello from controller'; //console.log(controllers); var template = angular.element( document.getElementById('template.html')).html(), compiled = $compile(template)(scope), obj = { render: { hello: "hello from 'fake' controller" }, hello: 'hello from other object.' }; scope.hello = "Hello from scope"; element.replaceWith(compiled); var result = $interpolate(template)(scope); templateStore.push(result); var result = $interpolate(template)(obj); templateStore.push(result); //console.log(result); //console.log(templateStore[0]); $('#test').append( // append just to test the saved template templateStore[0]); $('#test2').append( // append just to test the saved template templateStore[1]); }; } } } Render.$inject = ['$compile', '$interpolate']; 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> <div ng-app="myApp"> <script type="text/ng-template" id="template.html"> <div> <p>controllerAs: {{render.hello}}</p> scope: {{hello}} </div> </script> <h2>Compiled template with binding</h2> <render></render> <h2>The following is a string copy from above template with-out binding</h2> <div id="test"></div> <h2>You can also $interpolate a object with the following result (also no binding)</h2> <div id="test2"></div> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM