mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-04-27 19:13:55 +08:00
fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content the outer directive works but the inner directive never receives a transclusion function. This only failed if the first transclude directive was not the first directive found in compilation. Fixes #7240 Closes #7387
This commit is contained in:
@@ -924,7 +924,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
return linkFnFound ? compositeLinkFn : null;
|
return linkFnFound ? compositeLinkFn : null;
|
||||||
|
|
||||||
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
|
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
|
||||||
var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
|
var nodeLinkFn, childLinkFn, node, $node, childScope, i, ii, n;
|
||||||
|
|
||||||
// copy nodeList so that linking doesn't break due to live list updates.
|
// copy nodeList so that linking doesn't break due to live list updates.
|
||||||
var nodeListLength = nodeList.length,
|
var nodeListLength = nodeList.length,
|
||||||
@@ -946,14 +946,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
} else {
|
} else {
|
||||||
childScope = scope;
|
childScope = scope;
|
||||||
}
|
}
|
||||||
childTranscludeFn = nodeLinkFn.transclude;
|
|
||||||
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
|
// We need to create a new boundTranscludeFn if
|
||||||
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
|
// - a directive on this element wants to transclude
|
||||||
createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
|
// or
|
||||||
);
|
// - there is no boundTranscludeFn already and a transcludeFn was passed in
|
||||||
} else {
|
if ( nodeLinkFn.transcludeOnThisElement || (!boundTranscludeFn && transcludeFn) ) {
|
||||||
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
|
boundTranscludeFn = createBoundTranscludeFn(scope, nodeLinkFn.transclude || transcludeFn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
|
||||||
|
|
||||||
} else if (childLinkFn) {
|
} else if (childLinkFn) {
|
||||||
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
|
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
|
||||||
}
|
}
|
||||||
@@ -1329,7 +1332,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
||||||
nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
|
nodeLinkFn.transcludeOnThisElement = hasTranscludeDirective;
|
||||||
|
nodeLinkFn.transclude = childTranscludeFn;
|
||||||
|
|
||||||
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
|
previousCompileContext.hasElementTranscludeDirective = hasElementTranscludeDirective;
|
||||||
|
|
||||||
// might be normal or delayed nodeLinkFn depending on if templateUrl is present
|
// might be normal or delayed nodeLinkFn depending on if templateUrl is present
|
||||||
|
|||||||
@@ -1436,6 +1436,78 @@ describe('$compile', function() {
|
|||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
describe('nested transcludes', function() {
|
||||||
|
|
||||||
|
beforeEach(module(function($compileProvider) {
|
||||||
|
|
||||||
|
$compileProvider.directive('noop', valueFn({}));
|
||||||
|
|
||||||
|
$compileProvider.directive('sync', valueFn({
|
||||||
|
template: '<div ng-transclude></div>',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('async', valueFn({
|
||||||
|
templateUrl: 'async',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('syncSync', valueFn({
|
||||||
|
template: '<div noop><div sync><div ng-transclude></div></div></div>',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('syncAsync', valueFn({
|
||||||
|
template: '<div noop><div async><div ng-transclude></div></div></div>',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('asyncSync', valueFn({
|
||||||
|
templateUrl: 'asyncSync',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
$compileProvider.directive('asyncAsync', valueFn({
|
||||||
|
templateUrl: 'asyncAsync',
|
||||||
|
transclude: true
|
||||||
|
}));
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(inject(function($templateCache) {
|
||||||
|
$templateCache.put('async', '<div ng-transclude></div>');
|
||||||
|
$templateCache.put('asyncSync', '<div noop><div sync><div ng-transclude></div></div></div>');
|
||||||
|
$templateCache.put('asyncAsync', '<div noop><div async><div ng-transclude></div></div></div>');
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
it('should allow nested transclude directives with sync template containing sync template', inject(function($compile, $rootScope) {
|
||||||
|
element = $compile('<div sync-sync>transcluded content</div>')($rootScope);
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(element.text().trim()).toEqual('transcluded content');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should allow nested transclude directives with sync template containing async template', inject(function($compile, $rootScope) {
|
||||||
|
element = $compile('<div sync-async>transcluded content</div>')($rootScope);
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(element.text().trim()).toEqual('transcluded content');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should allow nested transclude directives with async template containing sync template', inject(function($compile, $rootScope) {
|
||||||
|
element = $compile('<div async-sync>transcluded content</div>')($rootScope);
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(element.text().trim()).toEqual('transcluded content');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should allow nested transclude directives with async template containing asynch template', inject(function($compile, $rootScope) {
|
||||||
|
element = $compile('<div async-async>transcluded content</div>')($rootScope);
|
||||||
|
$rootScope.$digest();
|
||||||
|
expect(element.text().trim()).toEqual('transcluded content');
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
it("should fail if replacing and template doesn't have a single root element", function() {
|
it("should fail if replacing and template doesn't have a single root element", function() {
|
||||||
module(function($exceptionHandlerProvider) {
|
module(function($exceptionHandlerProvider) {
|
||||||
$exceptionHandlerProvider.mode('log');
|
$exceptionHandlerProvider.mode('log');
|
||||||
|
|||||||
Reference in New Issue
Block a user