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.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();
});
});
}
};
});
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. 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.
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
: Creates DOM elements with angular binding to scope. That's what you would normally use to render your DOM to have two-way binding etc. working. 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.
$interpolate
: It is pretty similar to compile with the only difference that it will return the DOM elements wiht-out angular bindings.
You can see the difference if you have a look at the rendered html markup. Compiled templates have ng-binding
class in the markup and the other is just static html with-out that class.
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.
Please have a look at the demo below or at this 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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.