mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-13 08:59:54 +08:00
fix($compile): use the correct namespace for transcluded svg elements
This fixes the case when a directive that uses `templateUrl` is used inside of a transcluding directive like `ng-repeat`. Fixes #8808 Closes #8816
This commit is contained in:
@@ -955,26 +955,29 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
var compositeLinkFn =
|
||||
compileNodes($compileNodes, transcludeFn, $compileNodes,
|
||||
maxPriority, ignoreDirective, previousCompileContext);
|
||||
|
||||
compile.$$addScopeClass($compileNodes);
|
||||
|
||||
var namespace = null;
|
||||
var namespaceAdaptedCompileNodes = $compileNodes;
|
||||
var lastCompileNode;
|
||||
return function publicLinkFn(scope, cloneConnectFn, transcludeControllers, parentBoundTranscludeFn, futureParentElement){
|
||||
var namespace = null;
|
||||
assertArg(scope, 'scope');
|
||||
if (!namespace) {
|
||||
namespace = detectNamespaceForChildElements(futureParentElement);
|
||||
if (namespace !== 'html') {
|
||||
$compileNodes = jqLite(
|
||||
wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
|
||||
);
|
||||
}
|
||||
}
|
||||
if (namespace !== 'html' && $compileNodes[0] !== lastCompileNode) {
|
||||
namespaceAdaptedCompileNodes = jqLite(
|
||||
wrapTemplate(namespace, jqLite('<div>').append($compileNodes).html())
|
||||
);
|
||||
}
|
||||
// When using a directive with replace:true and templateUrl the $compileNodes
|
||||
// might change, so we need to recreate the namespace adapted compileNodes.
|
||||
lastCompileNode = $compileNodes[0];
|
||||
|
||||
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
|
||||
// and sometimes changes the structure of the DOM.
|
||||
var $linkNode = cloneConnectFn
|
||||
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
|
||||
: $compileNodes;
|
||||
? JQLitePrototype.clone.call(namespaceAdaptedCompileNodes) // IMPORTANT!!!
|
||||
: namespaceAdaptedCompileNodes;
|
||||
|
||||
if (transcludeControllers) {
|
||||
for (var controllerName in transcludeControllers) {
|
||||
@@ -1940,7 +1943,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
// it was cloned therefore we have to clone as well.
|
||||
linkNode = jqLiteClone(compileNode);
|
||||
}
|
||||
|
||||
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
|
||||
|
||||
// Copy in CSS classes from original node
|
||||
|
||||
@@ -289,6 +289,39 @@ describe('$compile', function() {
|
||||
|
||||
}));
|
||||
|
||||
it('should support directives with SVG templates and a slow url '+
|
||||
'that are stamped out later by a transcluding directive', function() {
|
||||
module(function() {
|
||||
directive('svgCircleUrl', valueFn({
|
||||
replace: true,
|
||||
templateUrl: 'template.html',
|
||||
templateNamespace: 'SVG',
|
||||
}));
|
||||
});
|
||||
inject(function($compile, $rootScope, $httpBackend) {
|
||||
$httpBackend.expect('GET', 'template.html').respond('<circle></circle>');
|
||||
element = $compile('<svg><svg-circle-url ng-repeat="l in list"/></svg>')($rootScope);
|
||||
|
||||
// initially the template is not yet loaded
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.list = [1];
|
||||
});
|
||||
expect(element.find('svg-circle-url').length).toBe(1);
|
||||
expect(element.find('circle').length).toBe(0);
|
||||
|
||||
// template is loaded and replaces the existing nodes
|
||||
$httpBackend.flush();
|
||||
expect(element.find('svg-circle-url').length).toBe(0);
|
||||
expect(element.find('circle').length).toBe(1);
|
||||
|
||||
// new entry should immediately use the loaded template
|
||||
$rootScope.$apply(function() {
|
||||
$rootScope.list.push(2);
|
||||
});
|
||||
expect(element.find('svg-circle-url').length).toBe(0);
|
||||
expect(element.find('circle').length).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user