问题
does anyone know how do I do ng-include from within a 'pre' tag? The usecase is that I have a website with some code blocks and some of the code blocks contain common code that I want to move to a separate partial. Example:
<pre>
My page-specific code....
<ng-include src="'partials/common-code.html'"></ng-include>
</pre>
Needless to say, this does not work, as the ng-include tag appears literally in the output...
thanks!
回答1:
You can do with a two directives: one is a sort of ngInclude, the other waits for the first to load the content and replaces itself with a pre
(http://plnkr.co/edit/fPy4M0ZK94erF31EeObE):
module.directive('myPre', function() {
return {
controller: function() {},
restrict: 'E',
link: function(scope, element, attrs, controller) {
controller.checkContent = function() {
if (!element.children().length) {
element.replaceWith('<pre>' + element.text() + '</pre>');
}
}
}
}
})
.directive('myPreTemplate', function($http) {
return {
require: '^myPre',
restrict: 'E',
link: function(scope, element, attrs, myPre) {
$http.get(attrs.src).then(function(res) {
element.replaceWith(res.data);
myPre.checkContent();
});
}
}
});
And you can use it like here:
<my-pre>
Code here...
<my-pre-template src="common.html"></my-pre-template>
...and here...
<my-pre-template src="common.html"></my-pre-template>
...and here again
</my-pre>
EDIT: to render the content of common template, the best way is using mustache (plunker updated):
...
$http.get(attrs.src).then(function(res) {
var rendered = Mustache.render(res, scope);
element.replaceWith(rendered);
myPre.checkContent();
});
...
回答2:
I was able to resolve it based on your idea of using a top-level custom pre directive, but using a different impl: I'm running a BFS algorithm, where each digest cycle I try to compile any direct sub pre-includes. Every iteration I wait until the inclusion children count is zero before checking if we need another cycle (using scope.$watch). Once done, I compile the entire my-pre to resolve any {{xxxx}} and convert it to pre. Working plunkr
// simulate a 3d party highligther (tested with HLJS)
.directive('myHighlighter', function($compile, $timeout) {
return {
restrict: 'E',
controller: function() {},
link: function(scope, element, attrs, controller) {
// wait for the end of the digest:
$timeout(function() {
$(element).replaceWith($('<pre>' + element.text() + '</pre>'));
});
}
}
})
// myPre will conert itself to the custom highlighter once done compiling:
.directive('myPre', function($compile, $timeout) {
return {
restrict: 'E',
controller: function() {},
link: {
pre: function(scope, element, attrs, controller) {
// limit the total inclusions allowed to avoid loops:
scope.it = 100;
// count inclusions:
scope.incCount = 0;
scope.$watch('incCount', function(newVal, oldVal, scope) {
if (oldVal !== newVal && newVal === 0) {
// watch the include tag count. When it's zero,
// see if we need another BFS pass for sub-children:
var children = $('pre-include', element).length;
if (children !== 0) {
$compile(element)(scope);
} else {
// If not, build the highlighter and we're done:
var e2 = $('<my-highlighter>' + element.html() + '</my-highlighter>');
$(element).replaceWith(e2);
$compile(e2)(scope);
}
}
});
},
post: function(scope, element, attrs, controller) {
}
}
}
})
.directive('preInclude', function($templateRequest, $compile) {
return {
link: {
pre: function(scope, element, attrs, myPre) {
scope.incCount++;
},
post: function(scope, element, attrs, myPre, transclude) {
scope.it--;
if (scope.it <= 0) {
console.log("max iterations reached, stopping");
return;
}
// enqueue the inclusion in the BFS queue:
$templateRequest(attrs.src).then(function(data) {
element.replaceWith(data);
scope.incCount--;
});
}
}
};
})
来源:https://stackoverflow.com/questions/34164294/angular-how-to-nest-templates-inside-pre-tags