Template for directive must have exactly one root element

While developing custom directives that provide their own template and use replace attribute to replace the directive element with your own template, you may run into following compile error.

Template for directive must have exactly one root element

When I ran into this issue, I found there were lot of different explanations given for it and different suggestions to get around this. Finally I started to look into core AngularJS code that throws this error. Following piece of code is responsible for this error.

$template = jqLite(trim(directiveValue));

if ($template.length != 1 || compileNode.nodeType !== 1) {
  throw $compileMinErr('tplrt',
      "Template for directive '{0}' must have exactly one root element. {1}",
      directiveName, '');
}

This code is executed when angular is applying your custom directive. As you can see that when a custom template is found for your directive, it is getting compiled and interpreted through jqLite (light weight version of jQuery). When jQuery compiles the templates, it creates array of elements it finds in that HTML template. Following snippet demonstrates what is happening in angularJS code.


var myTemplate = $("<div>foo</div><div>bar</div>");
if (myTemplate.length > 1) {
    alert('why would you do that to me!');
}

You can try it yourself. You will find that result of this jQuery compilation is two root nodes for each div. The check in angularJS code is doing following things.

  1. There is exactly one root node
  2. Second check in on node type. Node type 1 is ELEMENT type

When you are providing custom template for directive, you have to make sure that there is only one root element. And the root is a HTML element.

Well formed HTML

As jQuery and AngularJS expect that your HTML should be well formed. This means that your directive HTML should not have any mismatched tags or any other malformed HTML elements in it. When you are writing this template as string, the mismatched tags or other elements may not be visible in your HTML editor. When this happens, then jqLite compilation fails and finds that there are no elements for your template. That can be another reason when this AngularJS compile error is thrown. I follow a practice of writing my custom directive template in proper HTML editor and then copy that as string as in-line template for custom directive.

I hope this provides some insight into reason for, Template for directive must have exactly one root element, error.

comments powered by Disqus

Blog Tags