mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-27 15:04:02 +00:00
fix($compile): accessing controllers of transcluded directives from children
Additional API (backwards compatible) - Injects `$transclude` (see directive controllers) as 5th argument to directive link functions. - `$transclude` takes an optional scope as first parameter that overrides the bound scope. Deprecations: - `transclude` parameter of directive compile functions (use the new parameter for link functions instead). Refactorings: - Don't use comment node to temporarily store controllers - `ngIf`, `ngRepeat`, ... now all use `$transclude` Closes #4935.
This commit is contained in:
parent
c785918cbd
commit
90f87072e8
11 changed files with 434 additions and 73 deletions
|
|
@ -178,8 +178,9 @@
|
||||||
* * `$scope` - Current scope associated with the element
|
* * `$scope` - Current scope associated with the element
|
||||||
* * `$element` - Current element
|
* * `$element` - Current element
|
||||||
* * `$attrs` - Current attributes object for the element
|
* * `$attrs` - Current attributes object for the element
|
||||||
* * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
|
* * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.
|
||||||
* `function(cloneLinkingFn)`.
|
* The scope can be overridden by an optional first argument.
|
||||||
|
* `function([scope], cloneLinkingFn)`.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* #### `require`
|
* #### `require`
|
||||||
|
|
@ -272,7 +273,7 @@
|
||||||
* * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
|
* * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
|
||||||
* between all directive compile functions.
|
* between all directive compile functions.
|
||||||
*
|
*
|
||||||
* * `transclude` - A transclude linking function: `function(scope, cloneLinkingFn)`.
|
* * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
|
||||||
*
|
*
|
||||||
* <div class="alert alert-warning">
|
* <div class="alert alert-warning">
|
||||||
* **Note:** The template instance and the link instance may be different objects if the template has
|
* **Note:** The template instance and the link instance may be different objects if the template has
|
||||||
|
|
@ -281,6 +282,12 @@
|
||||||
* should be done in a linking function rather than in a compile function.
|
* should be done in a linking function rather than in a compile function.
|
||||||
* </div>
|
* </div>
|
||||||
*
|
*
|
||||||
|
* <div class="alert alert-error">
|
||||||
|
* **Note:** The `transclude` function that is passed to the compile function is deperecated, as it
|
||||||
|
* e.g. does not know about the right outer scope. Please use the transclude function that is passed
|
||||||
|
* to the link function instead.
|
||||||
|
* </div>
|
||||||
|
|
||||||
* A compile function can have a return value which can be either a function or an object.
|
* A compile function can have a return value which can be either a function or an object.
|
||||||
*
|
*
|
||||||
* * returning a (post-link) function - is equivalent to registering the linking function via the
|
* * returning a (post-link) function - is equivalent to registering the linking function via the
|
||||||
|
|
@ -295,7 +302,7 @@
|
||||||
* This property is used only if the `compile` property is not defined.
|
* This property is used only if the `compile` property is not defined.
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* function link(scope, iElement, iAttrs, controller) { ... }
|
* function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* The link function is responsible for registering DOM listeners as well as updating the DOM. It is
|
* The link function is responsible for registering DOM listeners as well as updating the DOM. It is
|
||||||
|
|
@ -316,6 +323,10 @@
|
||||||
* element defines a controller. The controller is shared among all the directives, which allows
|
* element defines a controller. The controller is shared among all the directives, which allows
|
||||||
* the directives to use the controllers as a communication channel.
|
* the directives to use the controllers as a communication channel.
|
||||||
*
|
*
|
||||||
|
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
|
||||||
|
* The scope can be overridden by an optional first argument. This is the same as the `$transclude`
|
||||||
|
* parameter of directive controllers.
|
||||||
|
* `function([scope], cloneLinkingFn)`.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* #### Pre-linking function
|
* #### Pre-linking function
|
||||||
|
|
@ -821,7 +832,7 @@ function $CompileProvider($provide) {
|
||||||
var compositeLinkFn =
|
var compositeLinkFn =
|
||||||
compileNodes($compileNodes, transcludeFn, $compileNodes,
|
compileNodes($compileNodes, transcludeFn, $compileNodes,
|
||||||
maxPriority, ignoreDirective, previousCompileContext);
|
maxPriority, ignoreDirective, previousCompileContext);
|
||||||
return function publicLinkFn(scope, cloneConnectFn){
|
return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
|
||||||
assertArg(scope, 'scope');
|
assertArg(scope, 'scope');
|
||||||
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
|
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
|
||||||
// and sometimes changes the structure of the DOM.
|
// and sometimes changes the structure of the DOM.
|
||||||
|
|
@ -829,6 +840,10 @@ function $CompileProvider($provide) {
|
||||||
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
|
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
|
||||||
: $compileNodes;
|
: $compileNodes;
|
||||||
|
|
||||||
|
forEach(transcludeControllers, function(instance, name) {
|
||||||
|
$linkNode.data('$' + name + 'Controller', instance);
|
||||||
|
});
|
||||||
|
|
||||||
// Attach scope only to non-text nodes.
|
// Attach scope only to non-text nodes.
|
||||||
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
|
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
|
||||||
var node = $linkNode[i];
|
var node = $linkNode[i];
|
||||||
|
|
@ -940,12 +955,19 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createBoundTranscludeFn(scope, transcludeFn) {
|
function createBoundTranscludeFn(scope, transcludeFn) {
|
||||||
return function boundTranscludeFn(cloneFn) {
|
return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
|
||||||
var transcludedScope = scope.$new(),
|
var scopeCreated = false;
|
||||||
clone;
|
|
||||||
transcludedScope.$$transcluded = true;
|
if (!transcludedScope) {
|
||||||
clone = transcludeFn(transcludedScope, cloneFn);
|
transcludedScope = scope.$new();
|
||||||
clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
|
transcludedScope.$$transcluded = true;
|
||||||
|
scopeCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var clone = transcludeFn(transcludedScope, cloneFn, controllers);
|
||||||
|
if (scopeCreated) {
|
||||||
|
clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
|
||||||
|
}
|
||||||
return clone;
|
return clone;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1086,9 +1108,9 @@ function $CompileProvider($provide) {
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
|
function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
|
||||||
return function(scope, element, attrs, controllers) {
|
return function(scope, element, attrs, controllers, transcludeFn) {
|
||||||
element = groupScan(element[0], attrStart, attrEnd);
|
element = groupScan(element[0], attrStart, attrEnd);
|
||||||
return linkFn(scope, element, attrs, controllers);
|
return linkFn(scope, element, attrs, controllers, transcludeFn);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1125,7 +1147,9 @@ function $CompileProvider($provide) {
|
||||||
controllerDirectives = previousCompileContext.controllerDirectives,
|
controllerDirectives = previousCompileContext.controllerDirectives,
|
||||||
newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
|
newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
|
||||||
templateDirective = previousCompileContext.templateDirective,
|
templateDirective = previousCompileContext.templateDirective,
|
||||||
transcludeDirective = previousCompileContext.transcludeDirective,
|
nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
|
||||||
|
hasTranscludeDirective = false,
|
||||||
|
hasElementTranscludeDirective = false,
|
||||||
$compileNode = templateAttrs.$$element = jqLite(compileNode),
|
$compileNode = templateAttrs.$$element = jqLite(compileNode),
|
||||||
directive,
|
directive,
|
||||||
directiveName,
|
directiveName,
|
||||||
|
|
@ -1176,15 +1200,18 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directiveValue = directive.transclude) {
|
if (directiveValue = directive.transclude) {
|
||||||
|
hasTranscludeDirective = true;
|
||||||
|
|
||||||
// Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
|
// Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
|
||||||
// This option should only be used by directives that know how to how to safely handle element transclusion,
|
// This option should only be used by directives that know how to how to safely handle element transclusion,
|
||||||
// where the transcluded nodes are added or replaced after linking.
|
// where the transcluded nodes are added or replaced after linking.
|
||||||
if (!directive.$$tlb) {
|
if (!directive.$$tlb) {
|
||||||
assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode);
|
assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
|
||||||
transcludeDirective = directive;
|
nonTlbTranscludeDirective = directive;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directiveValue == 'element') {
|
if (directiveValue == 'element') {
|
||||||
|
hasElementTranscludeDirective = true;
|
||||||
terminalPriority = directive.priority;
|
terminalPriority = directive.priority;
|
||||||
$template = groupScan(compileNode, attrStart, attrEnd);
|
$template = groupScan(compileNode, attrStart, attrEnd);
|
||||||
$compileNode = templateAttrs.$$element =
|
$compileNode = templateAttrs.$$element =
|
||||||
|
|
@ -1200,9 +1227,9 @@ function $CompileProvider($provide) {
|
||||||
// - newIsolateScopeDirective or templateDirective - combining templates with
|
// - newIsolateScopeDirective or templateDirective - combining templates with
|
||||||
// element transclusion doesn't make sense.
|
// element transclusion doesn't make sense.
|
||||||
//
|
//
|
||||||
// We need only transcludeDirective so that we prevent putting transclusion
|
// We need only nonTlbTranscludeDirective so that we prevent putting transclusion
|
||||||
// on the same element more than once.
|
// on the same element more than once.
|
||||||
transcludeDirective: transcludeDirective
|
nonTlbTranscludeDirective: nonTlbTranscludeDirective
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
$template = jqLite(jqLiteClone(compileNode)).contents();
|
$template = jqLite(jqLiteClone(compileNode)).contents();
|
||||||
|
|
@ -1271,7 +1298,7 @@ function $CompileProvider($provide) {
|
||||||
controllerDirectives: controllerDirectives,
|
controllerDirectives: controllerDirectives,
|
||||||
newIsolateScopeDirective: newIsolateScopeDirective,
|
newIsolateScopeDirective: newIsolateScopeDirective,
|
||||||
templateDirective: templateDirective,
|
templateDirective: templateDirective,
|
||||||
transcludeDirective: transcludeDirective
|
nonTlbTranscludeDirective: nonTlbTranscludeDirective
|
||||||
});
|
});
|
||||||
ii = directives.length;
|
ii = directives.length;
|
||||||
} else if (directive.compile) {
|
} else if (directive.compile) {
|
||||||
|
|
@ -1295,7 +1322,7 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
|
||||||
nodeLinkFn.transclude = transcludeDirective && childTranscludeFn;
|
nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
|
||||||
|
|
||||||
// might be normal or delayed nodeLinkFn depending on if templateUrl is present
|
// might be normal or delayed nodeLinkFn depending on if templateUrl is present
|
||||||
return nodeLinkFn;
|
return nodeLinkFn;
|
||||||
|
|
@ -1322,7 +1349,7 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function getControllers(require, $element) {
|
function getControllers(require, $element, elementControllers) {
|
||||||
var value, retrievalMethod = 'data', optional = false;
|
var value, retrievalMethod = 'data', optional = false;
|
||||||
if (isString(require)) {
|
if (isString(require)) {
|
||||||
while((value = require.charAt(0)) == '^' || value == '?') {
|
while((value = require.charAt(0)) == '^' || value == '?') {
|
||||||
|
|
@ -1332,13 +1359,12 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
optional = optional || value == '?';
|
optional = optional || value == '?';
|
||||||
}
|
}
|
||||||
|
value = null;
|
||||||
|
|
||||||
value = $element[retrievalMethod]('$' + require + 'Controller');
|
if (elementControllers && retrievalMethod === 'data') {
|
||||||
|
value = elementControllers[require];
|
||||||
if ($element[0].nodeType == 8 && $element[0].$$controller) { // Transclusion comment node
|
|
||||||
value = value || $element[0].$$controller;
|
|
||||||
$element[0].$$controller = null;
|
|
||||||
}
|
}
|
||||||
|
value = value || $element[retrievalMethod]('$' + require + 'Controller');
|
||||||
|
|
||||||
if (!value && !optional) {
|
if (!value && !optional) {
|
||||||
throw $compileMinErr('ctreq',
|
throw $compileMinErr('ctreq',
|
||||||
|
|
@ -1349,7 +1375,7 @@ function $CompileProvider($provide) {
|
||||||
} else if (isArray(require)) {
|
} else if (isArray(require)) {
|
||||||
value = [];
|
value = [];
|
||||||
forEach(require, function(require) {
|
forEach(require, function(require) {
|
||||||
value.push(getControllers(require, $element));
|
value.push(getControllers(require, $element, elementControllers));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
|
|
@ -1357,7 +1383,7 @@ function $CompileProvider($provide) {
|
||||||
|
|
||||||
|
|
||||||
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
|
||||||
var attrs, $element, i, ii, linkFn, controller, isolateScope;
|
var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
|
||||||
|
|
||||||
if (compileNode === linkNode) {
|
if (compileNode === linkNode) {
|
||||||
attrs = templateAttrs;
|
attrs = templateAttrs;
|
||||||
|
|
@ -1451,14 +1477,14 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
transcludeFn = boundTranscludeFn && controllersBoundTransclude;
|
||||||
if (controllerDirectives) {
|
if (controllerDirectives) {
|
||||||
forEach(controllerDirectives, function(directive) {
|
forEach(controllerDirectives, function(directive) {
|
||||||
var locals = {
|
var locals = {
|
||||||
$scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
|
$scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
|
||||||
$element: $element,
|
$element: $element,
|
||||||
$attrs: attrs,
|
$attrs: attrs,
|
||||||
$transclude: boundTranscludeFn
|
$transclude: transcludeFn
|
||||||
}, controllerInstance;
|
}, controllerInstance;
|
||||||
|
|
||||||
controller = directive.controller;
|
controller = directive.controller;
|
||||||
|
|
@ -1467,16 +1493,16 @@ function $CompileProvider($provide) {
|
||||||
}
|
}
|
||||||
|
|
||||||
controllerInstance = $controller(controller, locals);
|
controllerInstance = $controller(controller, locals);
|
||||||
|
// For directives with element transclusion the element is a comment,
|
||||||
// Directives with element transclusion and a controller need to attach controller
|
// but jQuery .data doesn't support attaching data to comment nodes as it's hard to
|
||||||
// to the comment node created by the compiler, but jQuery .data doesn't support
|
// clean up (http://bugs.jquery.com/ticket/8335).
|
||||||
// attaching data to comment nodes so instead we set it directly on the element and
|
// Instead, we save the controllers for the element in a local hash and attach to .data
|
||||||
// remove it after we read it later.
|
// later, once we have the actual element.
|
||||||
if ($element[0].nodeType == 8) { // Transclusion comment node
|
elementControllers[directive.name] = controllerInstance;
|
||||||
$element[0].$$controller = controllerInstance;
|
if (!hasElementTranscludeDirective) {
|
||||||
} else {
|
|
||||||
$element.data('$' + directive.name + 'Controller', controllerInstance);
|
$element.data('$' + directive.name + 'Controller', controllerInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (directive.controllerAs) {
|
if (directive.controllerAs) {
|
||||||
locals.$scope[directive.controllerAs] = controllerInstance;
|
locals.$scope[directive.controllerAs] = controllerInstance;
|
||||||
}
|
}
|
||||||
|
|
@ -1488,7 +1514,7 @@ function $CompileProvider($provide) {
|
||||||
try {
|
try {
|
||||||
linkFn = preLinkFns[i];
|
linkFn = preLinkFns[i];
|
||||||
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
|
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
|
||||||
linkFn.require && getControllers(linkFn.require, $element));
|
linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$exceptionHandler(e, startingTag($element));
|
$exceptionHandler(e, startingTag($element));
|
||||||
}
|
}
|
||||||
|
|
@ -1508,11 +1534,28 @@ function $CompileProvider($provide) {
|
||||||
try {
|
try {
|
||||||
linkFn = postLinkFns[i];
|
linkFn = postLinkFns[i];
|
||||||
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
|
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
|
||||||
linkFn.require && getControllers(linkFn.require, $element));
|
linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$exceptionHandler(e, startingTag($element));
|
$exceptionHandler(e, startingTag($element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is the function that is injected as `$transclude`.
|
||||||
|
function controllersBoundTransclude(scope, cloneAttachFn) {
|
||||||
|
var transcludeControllers;
|
||||||
|
|
||||||
|
// no scope passed
|
||||||
|
if (arguments.length < 2) {
|
||||||
|
cloneAttachFn = scope;
|
||||||
|
scope = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasElementTranscludeDirective) {
|
||||||
|
transcludeControllers = elementControllers;
|
||||||
|
}
|
||||||
|
|
||||||
|
return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1622,7 +1665,7 @@ function $CompileProvider($provide) {
|
||||||
|
|
||||||
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
|
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
|
||||||
success(function(content) {
|
success(function(content) {
|
||||||
var compileNode, tempTemplateAttrs, $template;
|
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
|
||||||
|
|
||||||
content = denormalizeTemplate(content);
|
content = denormalizeTemplate(content);
|
||||||
|
|
||||||
|
|
@ -1667,7 +1710,7 @@ function $CompileProvider($provide) {
|
||||||
var scope = linkQueue.shift(),
|
var scope = linkQueue.shift(),
|
||||||
beforeTemplateLinkNode = linkQueue.shift(),
|
beforeTemplateLinkNode = linkQueue.shift(),
|
||||||
linkRootElement = linkQueue.shift(),
|
linkRootElement = linkQueue.shift(),
|
||||||
controller = linkQueue.shift(),
|
boundTranscludeFn = linkQueue.shift(),
|
||||||
linkNode = $compileNode[0];
|
linkNode = $compileNode[0];
|
||||||
|
|
||||||
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
|
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
|
||||||
|
|
@ -1675,9 +1718,13 @@ function $CompileProvider($provide) {
|
||||||
linkNode = jqLiteClone(compileNode);
|
linkNode = jqLiteClone(compileNode);
|
||||||
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
|
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
|
||||||
}
|
}
|
||||||
|
if (afterTemplateNodeLinkFn.transclude) {
|
||||||
|
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
|
||||||
|
} else {
|
||||||
|
childBoundTranscludeFn = boundTranscludeFn;
|
||||||
|
}
|
||||||
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
|
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
|
||||||
controller);
|
childBoundTranscludeFn);
|
||||||
}
|
}
|
||||||
linkQueue = null;
|
linkQueue = null;
|
||||||
}).
|
}).
|
||||||
|
|
@ -1685,14 +1732,14 @@ function $CompileProvider($provide) {
|
||||||
throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
|
throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
|
||||||
});
|
});
|
||||||
|
|
||||||
return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) {
|
return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
|
||||||
if (linkQueue) {
|
if (linkQueue) {
|
||||||
linkQueue.push(scope);
|
linkQueue.push(scope);
|
||||||
linkQueue.push(node);
|
linkQueue.push(node);
|
||||||
linkQueue.push(rootElement);
|
linkQueue.push(rootElement);
|
||||||
linkQueue.push(controller);
|
linkQueue.push(boundTranscludeFn);
|
||||||
} else {
|
} else {
|
||||||
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller);
|
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,15 +86,14 @@ var ngIfDirective = ['$animate', function($animate) {
|
||||||
terminal: true,
|
terminal: true,
|
||||||
restrict: 'A',
|
restrict: 'A',
|
||||||
$$tlb: true,
|
$$tlb: true,
|
||||||
compile: function (element, attr, transclude) {
|
link: function ($scope, $element, $attr, ctrl, $transclude) {
|
||||||
return function ($scope, $element, $attr) {
|
|
||||||
var block, childScope;
|
var block, childScope;
|
||||||
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
|
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
|
||||||
|
|
||||||
if (toBoolean(value)) {
|
if (toBoolean(value)) {
|
||||||
if (!childScope) {
|
if (!childScope) {
|
||||||
childScope = $scope.$new();
|
childScope = $scope.$new();
|
||||||
transclude(childScope, function (clone) {
|
$transclude(childScope, function (clone) {
|
||||||
block = {
|
block = {
|
||||||
startNode: clone[0],
|
startNode: clone[0],
|
||||||
endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
|
endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
|
||||||
|
|
@ -115,7 +114,6 @@ var ngIfDirective = ['$animate', function($animate) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
|
||||||
|
|
@ -154,12 +154,12 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
||||||
priority: 400,
|
priority: 400,
|
||||||
terminal: true,
|
terminal: true,
|
||||||
transclude: 'element',
|
transclude: 'element',
|
||||||
compile: function(element, attr, transclusion) {
|
compile: function(element, attr) {
|
||||||
var srcExp = attr.ngInclude || attr.src,
|
var srcExp = attr.ngInclude || attr.src,
|
||||||
onloadExp = attr.onload || '',
|
onloadExp = attr.onload || '',
|
||||||
autoScrollExp = attr.autoscroll;
|
autoScrollExp = attr.autoscroll;
|
||||||
|
|
||||||
return function(scope, $element) {
|
return function(scope, $element, $attr, ctrl, $transclude) {
|
||||||
var changeCounter = 0,
|
var changeCounter = 0,
|
||||||
currentScope,
|
currentScope,
|
||||||
currentElement;
|
currentElement;
|
||||||
|
|
@ -188,7 +188,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
|
||||||
if (thisChangeId !== changeCounter) return;
|
if (thisChangeId !== changeCounter) return;
|
||||||
var newScope = scope.$new();
|
var newScope = scope.$new();
|
||||||
|
|
||||||
transclusion(newScope, function(clone) {
|
$transclude(newScope, function(clone) {
|
||||||
cleanupLastIncludeContent();
|
cleanupLastIncludeContent();
|
||||||
|
|
||||||
currentScope = newScope;
|
currentScope = newScope;
|
||||||
|
|
|
||||||
|
|
@ -201,8 +201,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
||||||
priority: 1000,
|
priority: 1000,
|
||||||
terminal: true,
|
terminal: true,
|
||||||
$$tlb: true,
|
$$tlb: true,
|
||||||
compile: function(element, attr, linker) {
|
link: function($scope, $element, $attr, ctrl, $transclude){
|
||||||
return function($scope, $element, $attr){
|
|
||||||
var expression = $attr.ngRepeat;
|
var expression = $attr.ngRepeat;
|
||||||
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
|
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
|
||||||
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
|
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
|
||||||
|
|
@ -364,7 +363,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
||||||
// jshint bitwise: true
|
// jshint bitwise: true
|
||||||
|
|
||||||
if (!block.startNode) {
|
if (!block.startNode) {
|
||||||
linker(childScope, function(clone) {
|
$transclude(childScope, function(clone) {
|
||||||
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
|
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
|
||||||
$animate.enter(clone, null, jqLite(previousNode));
|
$animate.enter(clone, null, jqLite(previousNode));
|
||||||
previousNode = clone;
|
previousNode = clone;
|
||||||
|
|
@ -377,7 +376,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
|
||||||
}
|
}
|
||||||
lastBlockMap = nextBlockMap;
|
lastBlockMap = nextBlockMap;
|
||||||
});
|
});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}];
|
}];
|
||||||
|
|
|
||||||
|
|
@ -160,10 +160,10 @@ var ngSwitchWhenDirective = ngDirective({
|
||||||
transclude: 'element',
|
transclude: 'element',
|
||||||
priority: 800,
|
priority: 800,
|
||||||
require: '^ngSwitch',
|
require: '^ngSwitch',
|
||||||
compile: function(element, attrs, transclude) {
|
compile: function(element, attrs) {
|
||||||
return function(scope, element, attr, ctrl) {
|
return function(scope, element, attr, ctrl, $transclude) {
|
||||||
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
|
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
|
||||||
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: transclude, element: element });
|
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -172,10 +172,8 @@ var ngSwitchDefaultDirective = ngDirective({
|
||||||
transclude: 'element',
|
transclude: 'element',
|
||||||
priority: 800,
|
priority: 800,
|
||||||
require: '^ngSwitch',
|
require: '^ngSwitch',
|
||||||
compile: function(element, attrs, transclude) {
|
link: function(scope, element, attr, ctrl, $transclude) {
|
||||||
return function(scope, element, attr, ctrl) {
|
ctrl.cases['?'] = (ctrl.cases['?'] || []);
|
||||||
ctrl.cases['?'] = (ctrl.cases['?'] || []);
|
ctrl.cases['?'].push({ transclude: $transclude, element: element });
|
||||||
ctrl.cases['?'].push({ transclude: transclude, element: element });
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -173,8 +173,7 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||||
terminal: true,
|
terminal: true,
|
||||||
priority: 400,
|
priority: 400,
|
||||||
transclude: 'element',
|
transclude: 'element',
|
||||||
compile: function(element, attr, linker) {
|
link: function(scope, $element, attr, ctrl, $transclude) {
|
||||||
return function(scope, $element, attr) {
|
|
||||||
var currentScope,
|
var currentScope,
|
||||||
currentElement,
|
currentElement,
|
||||||
autoScrollExp = attr.autoscroll,
|
autoScrollExp = attr.autoscroll,
|
||||||
|
|
@ -200,7 +199,7 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||||
|
|
||||||
if (template) {
|
if (template) {
|
||||||
var newScope = scope.$new();
|
var newScope = scope.$new();
|
||||||
linker(newScope, function(clone) {
|
$transclude(newScope, function(clone) {
|
||||||
clone.html(template);
|
clone.html(template);
|
||||||
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
$animate.enter(clone, null, currentElement || $element, function onNgViewEnter () {
|
||||||
if (angular.isDefined(autoScrollExp)
|
if (angular.isDefined(autoScrollExp)
|
||||||
|
|
@ -235,7 +234,6 @@ function ngViewFactory( $route, $anchorScroll, $compile, $controller,
|
||||||
cleanupLastView();
|
cleanupLastView();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3438,6 +3438,113 @@ describe('$compile', function() {
|
||||||
expect(log).toEqual('pre(); post(unicorn!)');
|
expect(log).toEqual('pre(); post(unicorn!)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should copy the directive controller to all clones', function() {
|
||||||
|
var transcludeCtrl, cloneCount = 2;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'content',
|
||||||
|
controller: function($transclude) {
|
||||||
|
transcludeCtrl = this;
|
||||||
|
},
|
||||||
|
link: function(scope, el, attr, ctrl, $transclude) {
|
||||||
|
var i;
|
||||||
|
for (i=0; i<cloneCount; i++) {
|
||||||
|
$transclude(cloneAttach);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneAttach(clone) {
|
||||||
|
el.append(clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude><span></span></div>')($rootScope);
|
||||||
|
var children = element.children(), i;
|
||||||
|
expect(transcludeCtrl).toBeDefined();
|
||||||
|
|
||||||
|
expect(element.data('$transcludeController')).toBe(transcludeCtrl);
|
||||||
|
for (i=0; i<cloneCount; i++) {
|
||||||
|
expect(children.eq(i).data('$transcludeController')).toBeUndefined();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should provide the $transclude controller local as 5th argument to the pre and post-link function', function() {
|
||||||
|
var ctrlTransclude, preLinkTransclude, postLinkTransclude;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'content',
|
||||||
|
controller: function($transclude) {
|
||||||
|
ctrlTransclude = $transclude;
|
||||||
|
},
|
||||||
|
compile: function() {
|
||||||
|
return {
|
||||||
|
pre: function(scope, el, attr, ctrl, $transclude) {
|
||||||
|
preLinkTransclude = $transclude;
|
||||||
|
},
|
||||||
|
post: function(scope, el, attr, ctrl, $transclude) {
|
||||||
|
postLinkTransclude = $transclude;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude></div>')($rootScope);
|
||||||
|
expect(ctrlTransclude).toBeDefined();
|
||||||
|
expect(ctrlTransclude).toBe(preLinkTransclude);
|
||||||
|
expect(ctrlTransclude).toBe(postLinkTransclude);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow an optional scope argument in $transclude', function() {
|
||||||
|
var capturedChildCtrl;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'content',
|
||||||
|
link: function(scope, element, attr, ctrl, $transclude) {
|
||||||
|
$transclude(scope, function(clone) {
|
||||||
|
element.append(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude>{{$id}}</div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
expect(element.text()).toBe($rootScope.$id);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should expose the directive controller to transcluded children', function() {
|
||||||
|
var capturedChildCtrl;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'content',
|
||||||
|
controller: function() {
|
||||||
|
},
|
||||||
|
link: function(scope, element, attr, ctrl, $transclude) {
|
||||||
|
$transclude(function(clone) {
|
||||||
|
element.append(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
directive('child', valueFn({
|
||||||
|
require: '^transclude',
|
||||||
|
link: function(scope, element, attr, ctrl) {
|
||||||
|
capturedChildCtrl = ctrl;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude><div child></div></div>')($rootScope);
|
||||||
|
expect(capturedChildCtrl).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3471,7 +3578,6 @@ describe('$compile', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('should only allow one element transclusion per element', function() {
|
it('should only allow one element transclusion per element', function() {
|
||||||
module(function() {
|
module(function() {
|
||||||
directive('first', valueFn({
|
directive('first', valueFn({
|
||||||
|
|
@ -3620,8 +3726,101 @@ describe('$compile', function() {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
it('should allow to access $transclude in the same directive', function() {
|
||||||
|
var _$transclude;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'element',
|
||||||
|
controller: function($transclude) {
|
||||||
|
_$transclude = $transclude;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude></div>')($rootScope);
|
||||||
|
expect(_$transclude).toBeDefined()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should copy the directive controller to all clones', function() {
|
||||||
|
var transcludeCtrl, cloneCount = 2;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'element',
|
||||||
|
controller: function() {
|
||||||
|
transcludeCtrl = this;
|
||||||
|
},
|
||||||
|
link: function(scope, el, attr, ctrl, $transclude) {
|
||||||
|
var i;
|
||||||
|
for (i=0; i<cloneCount; i++) {
|
||||||
|
$transclude(cloneAttach);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cloneAttach(clone) {
|
||||||
|
el.after(clone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div><div transclude></div></div>')($rootScope);
|
||||||
|
var children = element.children(), i;
|
||||||
|
for (i=0; i<cloneCount; i++) {
|
||||||
|
expect(children.eq(i).data('$transcludeController')).toBe(transcludeCtrl);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should expose the directive controller to transcluded children', function() {
|
||||||
|
var capturedTranscludeCtrl;
|
||||||
|
module(function() {
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'element',
|
||||||
|
controller: function() {
|
||||||
|
},
|
||||||
|
link: function(scope, element, attr, ctrl, $transclude) {
|
||||||
|
$transclude(scope, function(clone) {
|
||||||
|
element.after(clone);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
directive('child', valueFn({
|
||||||
|
require: '^transclude',
|
||||||
|
link: function(scope, element, attr, ctrl) {
|
||||||
|
capturedTranscludeCtrl = ctrl;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile) {
|
||||||
|
element = $compile('<div transclude><div child></div></div>')($rootScope);
|
||||||
|
expect(capturedTranscludeCtrl).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should allow access to $transclude in a templateUrl directive', function() {
|
||||||
|
var transclude;
|
||||||
|
module(function() {
|
||||||
|
directive('template', valueFn({
|
||||||
|
templateUrl: 'template.html',
|
||||||
|
replace: true
|
||||||
|
}));
|
||||||
|
directive('transclude', valueFn({
|
||||||
|
transclude: 'content',
|
||||||
|
controller: function($transclude) {
|
||||||
|
transclude = $transclude;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile, $httpBackend) {
|
||||||
|
$httpBackend.expectGET('template.html').respond('<div transclude></div>');
|
||||||
|
element = $compile('<div template></div>')($rootScope);
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(transclude).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
it('should safely create transclude comment node and not break with "-->"',
|
it('should safely create transclude comment node and not break with "-->"',
|
||||||
inject(function($rootScope) {
|
inject(function($rootScope) {
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,34 @@ describe('ngIf', function () {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ngIf and transcludes', function() {
|
||||||
|
it('should allow access to directive controller from children when used in a replace template', function() {
|
||||||
|
var controller;
|
||||||
|
module(function($compileProvider) {
|
||||||
|
var directive = $compileProvider.directive;
|
||||||
|
directive('template', valueFn({
|
||||||
|
template: '<div ng-if="true"><span test></span></div>',
|
||||||
|
replace: true,
|
||||||
|
controller: function() {
|
||||||
|
this.flag = true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
directive('test', valueFn({
|
||||||
|
require: '^template',
|
||||||
|
link: function(scope, el, attr, ctrl) {
|
||||||
|
controller = ctrl;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile, $rootScope) {
|
||||||
|
var element = $compile('<div><div template></div></div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
expect(controller.flag).toBe(true);
|
||||||
|
dealoc(element);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ngIf animations', function () {
|
describe('ngIf animations', function () {
|
||||||
var body, element, $rootElement;
|
var body, element, $rootElement;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -439,6 +439,36 @@ describe('ngInclude', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ngInclude and transcludes', function() {
|
||||||
|
it('should allow access to directive controller from children when used in a replace template', function() {
|
||||||
|
var controller;
|
||||||
|
module(function($compileProvider) {
|
||||||
|
var directive = $compileProvider.directive;
|
||||||
|
directive('template', valueFn({
|
||||||
|
template: '<div ng-include="\'include.html\'"></div>',
|
||||||
|
replace: true,
|
||||||
|
controller: function() {
|
||||||
|
this.flag = true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
directive('test', valueFn({
|
||||||
|
require: '^template',
|
||||||
|
link: function(scope, el, attr, ctrl) {
|
||||||
|
controller = ctrl;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile, $rootScope, $httpBackend) {
|
||||||
|
$httpBackend.expectGET('include.html').respond('<div><div test></div></div>');
|
||||||
|
var element = $compile('<div><div template></div></div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(controller.flag).toBe(true);
|
||||||
|
dealoc(element);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ngInclude animations', function() {
|
describe('ngInclude animations', function() {
|
||||||
var body, element, $rootElement;
|
var body, element, $rootElement;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1058,6 +1058,33 @@ describe('ngRepeat', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ngRepeat and transcludes', function() {
|
||||||
|
it('should allow access to directive controller from children when used in a replace template', function() {
|
||||||
|
var controller;
|
||||||
|
module(function($compileProvider) {
|
||||||
|
var directive = $compileProvider.directive;
|
||||||
|
directive('template', valueFn({
|
||||||
|
template: '<div ng-repeat="l in [1]"><span test></span></div>',
|
||||||
|
replace: true,
|
||||||
|
controller: function() {
|
||||||
|
this.flag = true;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
directive('test', valueFn({
|
||||||
|
require: '^template',
|
||||||
|
link: function(scope, el, attr, ctrl) {
|
||||||
|
controller = ctrl;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
inject(function($compile, $rootScope) {
|
||||||
|
var element = $compile('<div><div template></div></div>')($rootScope);
|
||||||
|
$rootScope.$apply();
|
||||||
|
expect(controller.flag).toBe(true);
|
||||||
|
dealoc(element);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ngRepeat animations', function() {
|
describe('ngRepeat animations', function() {
|
||||||
var body, element, $rootElement;
|
var body, element, $rootElement;
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,44 @@ describe('ngView', function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ngView and transcludes', function() {
|
||||||
|
it('should allow access to directive controller from children when used in a replace template', function() {
|
||||||
|
var controller;
|
||||||
|
module('ngRoute');
|
||||||
|
module(function($compileProvider, $routeProvider) {
|
||||||
|
$routeProvider.when('/view', {templateUrl: 'view.html'});
|
||||||
|
var directive = $compileProvider.directive;
|
||||||
|
directive('template', function() {
|
||||||
|
return {
|
||||||
|
template: '<div ng-view></div>',
|
||||||
|
replace: true,
|
||||||
|
controller: function() {
|
||||||
|
this.flag = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
directive('test', function() {
|
||||||
|
return {
|
||||||
|
require: '^template',
|
||||||
|
link: function(scope, el, attr, ctrl) {
|
||||||
|
controller = ctrl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
inject(function($compile, $rootScope, $httpBackend, $location) {
|
||||||
|
$httpBackend.expectGET('view.html').respond('<div><div test></div></div>');
|
||||||
|
var element = $compile('<div><div template></div></div>')($rootScope);
|
||||||
|
$location.url('/view');
|
||||||
|
$rootScope.$apply();
|
||||||
|
$httpBackend.flush();
|
||||||
|
expect(controller.flag).toBe(true);
|
||||||
|
dealoc(element);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ngView animations', function() {
|
describe('ngView animations', function() {
|
||||||
var body, element, $rootElement;
|
var body, element, $rootElement;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue