Directive (nested inside a partial) throws “Termplate must have exactly one root element”

All we need is an easy explanation of the problem, so here it is.

I’m trying to follow angular best practice recommendation and use directives to
encapsulate reusuable HTML elements.
The error message:

Error: Template must have exactly one root element. was: partials/user/path/to/somedata.html

the directive code:

.directive('stDirectivename', function() {
    return {
        restrict: 'E',
        replace: true,
        // transclude: false,
        template: 'partials/user/path/to/somedata.html'
    };
})

And the template:

<div ng-show="person.condition" class="someclass">
    <span class = "personRoi">
        <i class="anotherclass " ng-class="{'specialclass1': person.count>=0,'specialclass2':person.count<0}">

        </i>{{person.somedata}}%
    </span>
</div>

Called in the partial (which is the template of a modal) as:
<st-directivename></st-directivename>

when I replace the template url for a simple html string in the directive. Everything works. Unfortunately I can’t do that for the real template that involves both ' and. besides this solution won’t scale to the larger templates I plan to some directives.

Also when I just insert the template html instead of the directive tag, everything works correctly (I’m actually extracting the code from the existing html to make it reusable).

I read in other SO questions that this has to do with having extra space/tags/comments in the template. But I just can’t find such elements.

Does anybody know a solution for this? I’ll be glad for any help.

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

your mistake is: you must use templateUrl rather than template so as to indicate the path to the html partial

.directive('stDirectivename', function(){
    return {
        restrict:'E',
        replace:true,
        //transclude:false,
        templateUrl:'partials/user/path/to/somedata.html'

    };
})

Method 2

For those that may come after, also note that directive templates need to have –as the error says– only one root element i.e. multiple spans or divs must be enclosed in a root div.

Also note the comments on the OP: Whitespace or trailing comments in the template may result in this error as well.

It appears a fix to make Angular less temperamental about this may be included in the next release/update: github.com/angular/angular.js/issues/1459

Method 3

For those who are still looking for further clues…I ran into this same error when I had a typo in the templateUrl path of the directive. You get this error if you have replaced: true. Otherwise, you may see more wild error as WARNING: Tried to load angular more than once, which took me quite a while to figure out because the error message is really misleading.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply