Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 9c0418c

Browse files
committed
fix($compile): ignore ws when checking if template has single root
Also add the same error checking for sync templates. Closes #910
1 parent 1564b82 commit 9c0418c

File tree

2 files changed

+91
-18
lines changed

2 files changed

+91
-18
lines changed

src/ng/compile.js

+16-8
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ function $CompileProvider($provide) {
145145
Suffix = 'Directive',
146146
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
147147
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
148-
HAS_ROOT_ELEMENT = /^\<[\s\S]*\>$/;
148+
MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ';
149149

150150

151151
this.directive = function registerDirective(name, directiveFactory) {
@@ -587,8 +587,14 @@ function $CompileProvider($provide) {
587587
assertNoDuplicate('template', templateDirective, directive, $compileNode);
588588
templateDirective = directive;
589589

590-
compileNode = jqLite(directiveValue)[0];
590+
$template = jqLite('<div>' + trim(directiveValue) + '</div>').contents();
591+
compileNode = $template[0];
592+
591593
if (directive.replace) {
594+
if ($template.length != 1 || compileNode.nodeType !== 1) {
595+
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue);
596+
}
597+
592598
replaceWith($rootElement, $compileNode, compileNode);
593599

594600
var newTemplateAttrs = {$attr: {}};
@@ -840,15 +846,17 @@ function $CompileProvider($provide) {
840846

841847
$http.get(origAsyncDirective.templateUrl, {cache: $templateCache}).
842848
success(function(content) {
843-
if (replace && !content.match(HAS_ROOT_ELEMENT)) {
844-
throw Error('Template must have exactly one root element: ' + content);
845-
}
846-
847-
var compileNode, tempTemplateAttrs;
849+
var compileNode, tempTemplateAttrs, $template;
848850

849851
if (replace) {
852+
$template = jqLite('<div>' + trim(content) + '</div>').contents();
853+
compileNode = $template[0];
854+
855+
if ($template.length != 1 || compileNode.nodeType !== 1) {
856+
throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content);
857+
}
858+
850859
tempTemplateAttrs = {$attr: {}};
851-
compileNode = jqLite(content)[0];
852860
replaceWith($rootElement, $compileNode, compileNode);
853861
collectDirectives(compileNode, directives, tempTemplateAttrs);
854862
mergeTemplateAttributes(tAttrs, tempTemplateAttrs);

test/ng/compileSpec.js

+75-10
Original file line numberDiff line numberDiff line change
@@ -487,10 +487,48 @@ describe('$compile', function() {
487487
expect(child).toHaveClass('three');
488488
expect(child).toHaveClass('log'); // merged from replace directive template
489489
}));
490+
491+
it("should fail if replacing and template doesn't have a single root element", function() {
492+
module(function($compileProvider) {
493+
$compileProvider.directive('noRootElem', function() {
494+
return {
495+
replace: true,
496+
template: 'dada'
497+
}
498+
});
499+
$compileProvider.directive('multiRootElem', function() {
500+
return {
501+
replace: true,
502+
template: '<div></div><div></div>'
503+
}
504+
});
505+
$compileProvider.directive('singleRootWithWhiteSpace', function() {
506+
return {
507+
replace: true,
508+
template: ' <div></div> \n'
509+
}
510+
});
511+
});
512+
513+
inject(function($compile) {
514+
expect(function() {
515+
$compile('<p no-root-elem></p>');
516+
}).toThrow('Template must have exactly one root element. was: dada');
517+
518+
expect(function() {
519+
$compile('<p multi-root-elem></p>');
520+
}).toThrow('Template must have exactly one root element. was: <div></div><div></div>');
521+
522+
// ws is ok
523+
expect(function() {
524+
$compile('<p single-root-with-white-space></p>');
525+
}).not.toThrow();
526+
});
527+
});
490528
});
491529

492530

493-
describe('async templates', function() {
531+
describe('templateUrl', function() {
494532

495533
beforeEach(module(
496534
function($compileProvider) {
@@ -916,15 +954,6 @@ describe('$compile', function() {
916954
});
917955

918956

919-
it('should check that template has root element', inject(function($compile, $httpBackend) {
920-
$httpBackend.expect('GET', 'hello.html').respond('before <b>mid</b> after');
921-
$compile('<div i-hello></div>');
922-
expect(function(){
923-
$httpBackend.flush();
924-
}).toThrow('Template must have exactly one root element: before <b>mid</b> after');
925-
}));
926-
927-
928957
it('should allow multiple elements in template', inject(function($compile, $httpBackend) {
929958
$httpBackend.expect('GET', 'hello.html').respond('before <b>mid</b> after');
930959
element = jqLite('<div hello></div>');
@@ -958,6 +987,42 @@ describe('$compile', function() {
958987
expect(element.text()).toEqual('i=1;i=2;');
959988
}
960989
));
990+
991+
992+
it("should fail if replacing and template doesn't have a single root element", function() {
993+
module(function($exceptionHandlerProvider, $compileProvider) {
994+
$exceptionHandlerProvider.mode('log');
995+
996+
$compileProvider.directive('template', function() {
997+
return {
998+
replace: true,
999+
templateUrl: 'template.html'
1000+
}
1001+
});
1002+
});
1003+
1004+
inject(function($compile, $templateCache, $rootScope, $exceptionHandler) {
1005+
// no root element
1006+
$templateCache.put('template.html', 'dada');
1007+
$compile('<p template></p>');
1008+
$rootScope.$digest();
1009+
expect($exceptionHandler.errors.pop().message).
1010+
toBe('Template must have exactly one root element. was: dada');
1011+
1012+
// multi root
1013+
$templateCache.put('template.html', '<div></div><div></div>');
1014+
$compile('<p template></p>');
1015+
$rootScope.$digest();
1016+
expect($exceptionHandler.errors.pop().message).
1017+
toBe('Template must have exactly one root element. was: <div></div><div></div>');
1018+
1019+
// ws is ok
1020+
$templateCache.put('template.html', ' <div></div> \n');
1021+
$compile('<p template></p>');
1022+
$rootScope.$apply();
1023+
expect($exceptionHandler.errors).toEqual([]);
1024+
});
1025+
});
9611026
});
9621027

9631028

0 commit comments

Comments
 (0)