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

fix(ngInclude): correctly add non-html namespaced template content #8981

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions src/.jshintrc
Original file line number Diff line number Diff line change
@@ -124,6 +124,8 @@
"jqLiteAddNodes": false,
"jqLiteController": false,
"jqLiteInheritedData": false,
"jqLiteBuildFragment": false,
"jqLiteParseHTML": false,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the jqLiteParseHTML addition doesn't matter much, but I don't think it's bad to have it

"getBooleanAttrName": false,
"getAliasedAttrName": false,
"createEventHandler": false,
12 changes: 12 additions & 0 deletions src/ng/directive/ngInclude.js
Original file line number Diff line number Diff line change
@@ -267,6 +267,18 @@ var ngIncludeFillContentDirective = ['$compile',
priority: -400,
require: 'ngInclude',
link: function(scope, $element, $attr, ctrl) {
if (/SVG/.test($element[0].toString())) {
// WebKit: https://bugs.webkit.org/show_bug.cgi?id=135698 --- SVG elements do not
// support innerHTML, so detect this here and try to generate the contents
// specially.
$element.empty();
$compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
function namespaceAdaptedClone(clone) {
$element.append(clone);
}, undefined, undefined, $element);
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add a blank line after this line


$element.html(ctrl.template);
$compile($element.contents())(scope);
}
40 changes: 40 additions & 0 deletions test/ng/directive/ngIncludeSpec.js
Original file line number Diff line number Diff line change
@@ -362,6 +362,46 @@ describe('ngInclude', function() {
}));


it('should construct SVG template elements with correct namespace', function() {
if (!window.SVGRectElement) return;
module(function($compileProvider) {
$compileProvider.directive('test', valueFn({
templateNamespace: 'svg',
templateUrl: 'my-rect.html',
replace: true
}));
});
inject(function($compile, $rootScope, $httpBackend) {
$httpBackend.expectGET('my-rect.html').respond('<g ng-include="\'include.svg\'"></g>');
$httpBackend.expectGET('include.svg').respond('<rect></rect><rect></rect>');
element = $compile('<svg><test></test></svg>')($rootScope);
$httpBackend.flush();
var child = element.find('rect');
expect(child.length).toBe(2);
expect(child[0] instanceof SVGRectElement).toBe(true);
});
});


it('should compile only the template content of an SVG template', function() {
if (!window.SVGRectElement) return;
module(function($compileProvider) {
$compileProvider.directive('test', valueFn({
templateNamespace: 'svg',
templateUrl: 'my-rect.html',
replace: true
}));
});
inject(function($compile, $rootScope, $httpBackend) {
$httpBackend.expectGET('my-rect.html').respond('<g ng-include="\'include.svg\'"><a></a></g>');
$httpBackend.expectGET('include.svg').respond('<rect></rect><rect></rect>');
element = $compile('<svg><test></test></svg>')($rootScope);
$httpBackend.flush();
expect(element.find('a').length).toBe(0);
});
});


describe('autoscroll', function() {
var autoScrollSpy;