frosty frosty - 8 days ago 4
AngularJS Question

Reuse Angular's template function

In Angular, you can inject the

$compile
service, and you can compile things on the fly. Like this:

let compiledElement = $compile('<my-elem></my-elem>')(myScope);


So what I want to know is if it is possible to save the result of the first call to
$compile
so that it can be reused. Something like this:

let templateFunction = $compile('<my-elem></my-elem>');
cacheTemplateFunction(templateFunction);
let compiledElement = templateFunction(myScope);


Practically, here is what my code looks like:

const cachedTemplateFunction = {};

function compileRawHtml(html, scope){
let compiledEl;
if(cachedTemplateFunction[html]){
let tempFunc = cachedTemplateFunction[html];
compiledEl = tempFunc(scope)
} else {
let tempFunc = $compile(html);
cachedTemplateFunction[html] = tempFunc;
compiledEl = tempFunc(scope);
}
}


So the first time through with that template, it will compile and cache the template function. Then the second time through it reuses it. When I call this, I get an error about childNodes of undefined. So am I to assume that you can't reuse the template function that is returned from the $compile call?

Answer

When you call $compile, it returns what is called a publicLinkFn. This function can be saved and called to bypass subsequent calls to the compile function. The only caveat is that you have to pass a second parameter to the publicLinkFn, which parameter is called a cloneAttachFn. The internals of Angular will call your cloneAttachFn, and pass two parameters to you. First will be a cloned copy of the element that you called $compile with. The second will be the scope for the clonedElement. Your cloneAttachFn needs to attach the element to the DOM. If it doesn't, you will get an error.

The only thing that needs to be changed in the above code is the following:

tempFunc(scope, (clonedEl, currentScope)=>{
    //You simply need to attach the clonedEl to the DOM
    angular.element('.some-selector').append(clonedEl);
})