diff --git a/src/ng/compile.js b/src/ng/compile.js
index 9285b253d0b3..eff69b5dee39 100644
--- a/src/ng/compile.js
+++ b/src/ng/compile.js
@@ -498,7 +498,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var hasDirectives = {},
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
- CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
+ CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
+ TABLE_CONTENT_REGEXP = /^<\s*(tr|th|td|tbody)(\s+[^>]*)?>/i;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
@@ -1239,9 +1240,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (directive.replace) {
replaceDirective = directive;
- $template = jqLite('
' +
- trim(directiveValue) +
- '
').contents();
+ $template = directiveTemplateContents(directiveValue);
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
@@ -1639,6 +1638,28 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
+ function directiveTemplateContents(template) {
+ var type;
+ template = trim(template);
+ if ((type = TABLE_CONTENT_REGEXP.exec(template))) {
+ type = type[1].toLowerCase();
+ var table = jqLite(''),
+ tbody = table.children('tbody'),
+ leaf = /(td|th)/.test(type) && table.find('tr');
+ if (tbody.length && type !== 'tbody') {
+ table = tbody;
+ }
+ if (leaf && leaf.length) {
+ table = leaf;
+ }
+ return table.contents();
+ }
+ return jqLite('' +
+ template +
+ '
').contents();
+ }
+
+
function compileTemplateUrl(directives, $compileNode, tAttrs,
$rootElement, childTranscludeFn, preLinkFns, postLinkFns, previousCompileContext) {
var linkQueue = [],
@@ -1663,7 +1684,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
content = denormalizeTemplate(content);
if (origAsyncDirective.replace) {
- $template = jqLite('' + trim(content) + '
').contents();
+ $template = directiveTemplateContents(content);
compileNode = $template[0];
if ($template.length != 1 || compileNode.nodeType !== 1) {
diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js
index 39e236959635..d75c1b3c53b6 100755
--- a/test/ng/compileSpec.js
+++ b/test/ng/compileSpec.js
@@ -512,6 +512,22 @@ describe('$compile', function() {
expect(element).toBe(attr.$$element);
}
}));
+ directive('replaceWithTr', valueFn({
+ replace: true,
+ template: 'TR |
'
+ }));
+ directive('replaceWithTd', valueFn({
+ replace: true,
+ template: 'TD | '
+ }));
+ directive('replaceWithTh', valueFn({
+ replace: true,
+ template: 'TH | '
+ }));
+ directive('replaceWithTbody', valueFn({
+ replace: true,
+ template: 'TD |
'
+ }));
}));
@@ -675,6 +691,34 @@ describe('$compile', function() {
}).not.toThrow();
});
});
+
+ it('should support templates with root tags', inject(function($compile, $rootScope) {
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ expect(nodeName_(element)).toMatch(/tr/i);
+ }));
+
+ it('should support templates with root tags', inject(function($compile, $rootScope) {
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ expect(nodeName_(element)).toMatch(/td/i);
+ }));
+
+ it('should support templates with root | tags', inject(function($compile, $rootScope) {
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ expect(nodeName_(element)).toMatch(/th/i);
+ }));
+
+ it('should support templates with root |
tags', inject(function($compile, $rootScope) {
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ expect(nodeName_(element)).toMatch(/tbody/i);
+ }));
});
@@ -771,6 +815,23 @@ describe('$compile', function() {
replace: true,
template: 'Hello, {{name}}!'
}));
+
+ directive('replaceWithTr', valueFn({
+ replace: true,
+ templateUrl: 'tr.html'
+ }));
+ directive('replaceWithTd', valueFn({
+ replace: true,
+ templateUrl: 'td.html'
+ }));
+ directive('replaceWithTh', valueFn({
+ replace: true,
+ templateUrl: 'th.html'
+ }));
+ directive('replaceWithTbody', valueFn({
+ replace: true,
+ templateUrl: 'tbody.html'
+ }));
}
));
@@ -1386,6 +1447,42 @@ describe('$compile', function() {
expect(element.html()).toContain('i = 1');
});
});
+
+ it('should support templates with root tags', inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('tr.html', '
TR |
');
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ $rootScope.$digest();
+ expect(nodeName_(element)).toMatch(/tr/i);
+ }));
+
+ it('should support templates with root tags', inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('td.html', ' | TD | ');
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ $rootScope.$digest();
+ expect(nodeName_(element)).toMatch(/td/i);
+ }));
+
+ it('should support templates with root tags', inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('th.html', ' | TH | ');
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ $rootScope.$digest();
+ expect(nodeName_(element)).toMatch(/th/i);
+ }));
+
+ it('should support templates with root tags', inject(function($compile, $rootScope, $templateCache) {
+ $templateCache.put('tbody.html', 'TD |
');
+ expect(function() {
+ element = $compile('')($rootScope);
+ }).not.toThrow();
+ $rootScope.$digest();
+ expect(nodeName_(element)).toMatch(/tbody/i);
+ }));
});