From 984dc4be46c4aebdbd68d8a46ede428ce95f903b Mon Sep 17 00:00:00 2001 From: Andreas Pelme Date: Sat, 17 Aug 2013 16:25:05 +0200 Subject: [PATCH] fix($compile): properly handle directive replace for table elements To work around limitations in jqLite, the template snippet is wrapped in a
element. This does not work for table elements, since they cannot be constructed inside a div. This patch takes special to properly wrap caption, thead, tbody, tfoot, tr, th and td in tags that allow them to be created. Closes #1459 --- src/ng/compile.js | 25 ++++++++-- test/ng/compileSpec.js | 106 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 5 deletions(-) diff --git a/src/ng/compile.js b/src/ng/compile.js index 7a2ee4e7fcf8..6ed3c229992d 100644 --- a/src/ng/compile.js +++ b/src/ng/compile.js @@ -752,7 +752,8 @@ function $CompileProvider($provide) { childTranscludeFn = transcludeFn, controllerDirectives, linkFn, - directiveValue; + directiveValue, + directiveValueTrimmed; // executes all directives on the current element for(var i = 0, ii = directives.length; i < ii; i++) { @@ -821,11 +822,25 @@ function $CompileProvider($provide) { if (directive.replace) { replaceDirective = directive; - $template = jqLite('
' + - trim(directiveValue) + - '
').contents(); - compileNode = $template[0]; + directiveValueTrimmed = trim(directiveValue); + + // Special case for table elements that cannot be wrapped in a div + if (directiveValueTrimmed.indexOf('' + directiveValueTrimmed + '').children().contents(); + } + else if (['' + directiveValueTrimmed + '').contents(); + } + else if (['' + directiveValueTrimmed + '').children().children().contents(); + } + else { + $template = jqLite('
' + directiveValueTrimmed + '
').contents(); + } + + compileNode = $template[0]; if ($template.length != 1 || compileNode.nodeType !== 1) { throw $compileMinErr('tplrt', "Template for directive '{0}' must have exactly one root element. {1}", directiveName, ''); } diff --git a/test/ng/compileSpec.js b/test/ng/compileSpec.js index 28dc57fef0f8..d64e478f69d3 100755 --- a/test/ng/compileSpec.js +++ b/test/ng/compileSpec.js @@ -489,8 +489,114 @@ describe('$compile', function() { expect(element).toBe(attr.$$element); } })); + + directive('replaceTr', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceTd', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceTh', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceThead', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceTbody', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceTfoot', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + directive('replaceCaption', valueFn({ + replace: true, + template: 'Replace!', + compile: function(element, attr) { + attr.$set('compiled', 'COMPILED'); + expect(element).toBe(attr.$$element); + } + })); + + })); + it('should replace tr element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.text()).toEqual('Replace!'); + expect(element.find('tr').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace td element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.text()).toEqual('Replace!'); + expect(element.find('td').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace th element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.text()).toEqual('Replace!'); + expect(element.find('th').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace thead element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.find('td').text()).toEqual('Replace!'); + expect(element.find('thead').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace tbody element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.find('td').text()).toEqual('Replace!'); + expect(element.find('tbody').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace tfoot element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.find('td').text()).toEqual('Replace!'); + expect(element.find('tfoot').attr('compiled')).toEqual('COMPILED'); + })); + + it('should replace caption element with template', inject(function($compile, $rootScope) { + element = $compile('
')($rootScope); + expect(element.find('caption').text()).toEqual('Replace!'); + expect(element.find('caption').attr('compiled')).toEqual('COMPILED'); + })); it('should replace element with template', inject(function($compile, $rootScope) { element = $compile('
ignore
')($rootScope);