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

Fix $compile (remove templateUrl directive splitting) #3927

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 29 additions & 28 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ function $CompileProvider($provide) {
directives = collectDirectives(nodeList[i], [], attrs, i == 0 ? maxPriority : undefined, ignoreDirective);

nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement, null, [], [])
: null;

childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes || !nodeList[i].childNodes.length)
Expand Down Expand Up @@ -734,12 +734,13 @@ function $CompileProvider($provide) {
* scope argument is auto-generated to the new child of the transcluded parent scope.
* @param {JQLite} jqCollection If we are working on the root of the compile tree then this
* argument has the root jqLite array so that we can replace nodes on it.
* @param {Object=} ignoreDirective An optional directive that will be ignored when compiling
* the transclusion.
* @returns linkFn
*/
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection, originalReplaceDirective) {
function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn,
jqCollection, ignoreDirective, preLinkFns, postLinkFns) {
var terminalPriority = -Number.MAX_VALUE,
preLinkFns = [],
postLinkFns = [],
newScopeDirective = null,
newIsolateScopeDirective = null,
templateDirective = null,
Expand All @@ -748,7 +749,6 @@ function $CompileProvider($provide) {
directiveName,
$template,
transcludeDirective,
replaceDirective = originalReplaceDirective,
childTranscludeFn = transcludeFn,
controllerDirectives,
linkFn,
Expand All @@ -771,18 +771,22 @@ function $CompileProvider($provide) {
}

if (directiveValue = directive.scope) {
assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);
if (isObject(directiveValue)) {
safeAddClass($compileNode, 'ng-isolate-scope');
newIsolateScopeDirective = directive;
}
safeAddClass($compileNode, 'ng-scope');
newScopeDirective = newScopeDirective || directive;

if (!directive.templateUrl) {
assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode);
if (isObject(directiveValue)) {
safeAddClass($compileNode, 'ng-isolate-scope');
newIsolateScopeDirective = directive;
}
safeAddClass($compileNode, 'ng-scope');
}
}

directiveName = directive.name;

if (directiveValue = directive.controller) {
if (!directive.templateUrl && directive.controller) {
directiveValue = directive.controller;
controllerDirectives = controllerDirectives || {};
assertNoDuplicate("'" + directiveName + "' controller",
controllerDirectives[directiveName], directive, $compileNode);
Expand All @@ -801,7 +805,7 @@ function $CompileProvider($provide) {
replaceWith(jqCollection, jqLite(sliceArgs($template)), compileNode);

childTranscludeFn = compile($template, transcludeFn, terminalPriority,
replaceDirective && replaceDirective.name);
ignoreDirective && ignoreDirective.name);
} else {
$template = jqLite(JQLiteClone(compileNode)).contents();
$compileNode.html(''); // clear contents
Expand All @@ -820,7 +824,7 @@ function $CompileProvider($provide) {
directiveValue = denormalizeTemplate(directiveValue);

if (directive.replace) {
replaceDirective = directive;
ignoreDirective = directive;
$template = jqLite('<div>' +
trim(directiveValue) +
'</div>').contents();
Expand Down Expand Up @@ -859,10 +863,11 @@ function $CompileProvider($provide) {
templateDirective = directive;

if (directive.replace) {
replaceDirective = directive;
ignoreDirective = directive;
}
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i),
nodeLinkFn, $compileNode, templateAttrs, jqCollection, childTranscludeFn);

nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
templateAttrs, jqCollection, childTranscludeFn, preLinkFns, postLinkFns);
ii = directives.length;
} else if (directive.compile) {
try {
Expand Down Expand Up @@ -1143,16 +1148,16 @@ function $CompileProvider($provide) {
}


function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs,
$rootElement, childTranscludeFn) {
function compileTemplateUrl(directives, $compileNode, tAttrs,
$rootElement, childTranscludeFn, preLinkFns, postLinkFns) {
var linkQueue = [],
afterTemplateNodeLinkFn,
afterTemplateChildLinkFn,
beforeTemplateCompileNode = $compileNode[0],
origAsyncDirective = directives.shift(),
// The fact that we have to copy and patch the directive seems wrong!
derivedSyncDirective = extend({}, origAsyncDirective, {
controller: null, templateUrl: null, transclude: null, scope: null, replace: null
templateUrl: null, transclude: null, replace: null
}),
templateUrl = (isFunction(origAsyncDirective.templateUrl))
? origAsyncDirective.templateUrl($compileNode, tAttrs)
Expand Down Expand Up @@ -1186,7 +1191,8 @@ function $CompileProvider($provide) {

directives.unshift(derivedSyncDirective);

afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn, $compileNode, origAsyncDirective);
afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs,
childTranscludeFn, $compileNode, origAsyncDirective, preLinkFns, postLinkFns);
forEach($rootElement, function(node, i) {
if (node == compileNode) {
$rootElement[i] = $compileNode[0];
Expand All @@ -1208,10 +1214,7 @@ function $CompileProvider($provide) {
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
}

afterTemplateNodeLinkFn(
beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller),
scope, linkNode, $rootElement, controller
);
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller);
}
linkQueue = null;
}).
Expand All @@ -1226,9 +1229,7 @@ function $CompileProvider($provide) {
linkQueue.push(rootElement);
linkQueue.push(controller);
} else {
afterTemplateNodeLinkFn(function() {
beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);
}, scope, node, rootElement, controller);
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);
}
};
}
Expand Down
42 changes: 33 additions & 9 deletions test/ng/compileSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1264,6 +1264,35 @@ describe('$compile', function() {
expect(element.text()).toBe('boom!1|boom!2|');
});
});


it('should support templateUrl with replace', function() {
// a regression https://github.com/angular/angular.js/issues/3792
module(function($compileProvider) {
$compileProvider.directive('simple', function() {
return {
templateUrl: '/some.html',
replace: true
};
});
});

inject(function($templateCache, $rootScope, $compile) {
$templateCache.put('/some.html',
'<div ng-switch="i">' +
'<div ng-switch-when="1">i = 1</div>' +
'<div ng-switch-default>I dont know what `i` is.</div>' +
'</div>');

element = $compile('<div simple></div>')($rootScope);

$rootScope.$apply(function() {
$rootScope.i = 1;
});

expect(element.html()).toContain('i = 1');
});
});
});


Expand Down Expand Up @@ -2824,7 +2853,7 @@ describe('$compile', function() {
});


it('should make the result of a transclusion available to the parent directive in pre- and post- linking phase (templateUrl)',
it('should make the result of a transclusion available to the parent directive in post- linking phase (templateUrl)',
function() {
// when compiling an async directive the transclusion is always processed before the directive
// this is different compared to sync directive. delaying the transclusion makes little sense.
Expand All @@ -2834,13 +2863,8 @@ describe('$compile', function() {
return {
transclude: true,
templateUrl: 'trans.html',
link: {
pre: function($scope, $element) {
log('pre(' + $element.text() + ')');
},
post: function($scope, $element) {
log('post(' + $element.text() + ')');
}
link: function($scope, $element) {
log('post(' + $element.text() + ')');
}
};
});
Expand All @@ -2850,7 +2874,7 @@ describe('$compile', function() {

element = $compile('<div trans><span>unicorn!</span></div>')($rootScope);
$rootScope.$apply();
expect(log).toEqual('pre(unicorn!); post(unicorn!)');
expect(log).toEqual('post(unicorn!)');
});
});
});
Expand Down