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

Commit

Permalink
fix(compiler): allow transclusion of root elements
Browse files Browse the repository at this point in the history
Fixed an issue where a directive that uses transclusion (such as ngRepeat) failed to link if it was declared on the root element of the compilation tree. (For example ngView or ngInclude including template where ngRepeat was the top most element).
  • Loading branch information
mhevery committed Mar 19, 2012
1 parent 6ecac8e commit 9918b74
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ function bindJQuery() {
JQLitePatchJQueryRemove('empty');
JQLitePatchJQueryRemove('html');
} else {
jqLite = jqLiteWrap;
jqLite = JQLite;
}
angular.element = jqLite;
}
Expand Down
2 changes: 1 addition & 1 deletion src/angular.suffix
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

publishExternalAPI(angular);

jqLiteWrap(document).ready(function() {
JQLite(document).ready(function() {
angularInit(document, bootstrap);
});

Expand Down
19 changes: 10 additions & 9 deletions src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,17 +168,18 @@ function JQLitePatchJQueryRemove(name, dispatchThis) {
}

/////////////////////////////////////////////
function jqLiteWrap(element) {
if (isString(element) && element.charAt(0) != '<') {
throw new Error('selectors not implemented');
}
return new JQLite(element);
}

function JQLite(element) {
if (element instanceof JQLite) {
return element;
} else if (isString(element)) {
}
if (!(this instanceof JQLite)) {
if (isString(element) && element.charAt(0) != '<') {
throw Error('selectors not implemented');
}
return new JQLite(element);
}

if (isString(element)) {
var div = document.createElement('div');
// Read about the NoScope elements here:
// http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx
Expand Down Expand Up @@ -299,7 +300,7 @@ var JQLitePrototype = JQLite.prototype = {

this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9
// we can not use jqLite since we are not done loading and jQuery could be loaded later.
jqLiteWrap(window).bind('load', trigger); // fallback to window.onload for others
JQLite(window).bind('load', trigger); // fallback to window.onload for others
},
toString: function() {
var value = [];
Expand Down
2 changes: 1 addition & 1 deletion src/scenario/angular.suffix
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ angular.forEach(script.attributes, function(attr) {
});

if (config.autotest) {
jqLiteWrap(document).ready(function() {
JQLite(document).ready(function() {
angular.scenario.setUpAndRun(config);
});
}
Expand Down
7 changes: 5 additions & 2 deletions src/service/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,10 @@ function $CompileProvider($provide) {
//================================

function compile(templateElement, transcludeFn, maxPriority) {
templateElement = jqLite(templateElement);
if (!(templateElement instanceof jqLite)) {
// jquery always rewraps, where as we need to preserve the original selector so that we can modify it.
templateElement = jqLite(templateElement);
}
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
forEach(templateElement, function(node, index){
Expand Down Expand Up @@ -488,7 +491,7 @@ function $CompileProvider($provide) {
template = jqLite(templateNode);
templateNode = (element = templateAttrs.$element = jqLite(
'<!-- ' + directiveName + ': ' + templateAttrs[directiveName] + ' -->'))[0];
template.replaceWith(templateNode);
replaceWith(rootElement, jqLite(template[0]), templateNode);
childTranscludeFn = compile(template, transcludeFn, terminalPriority);
} else {
template = jqLite(JQLiteClone(templateNode));
Expand Down
2 changes: 1 addition & 1 deletion test/jqLiteSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe('jqLite', function() {


it('should be jqLite when jqLiteMode is on, otherwise jQuery', function() {
expect(jqLite).toBe(_jqLiteMode ? jqLiteWrap : _jQuery);
expect(jqLite).toBe(_jqLiteMode ? JQLite : _jQuery);
});


Expand Down
22 changes: 22 additions & 0 deletions test/service/compilerSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1751,5 +1751,27 @@ describe('$compile', function() {
});
});


it('should support transcluded element on root content', function() {
var comment;
module(function($compileProvider) {
$compileProvider.directive('transclude', valueFn({
transclude: 'element',
compile: function(element, attr, linker) {
return function(scope, element, attr) {
comment = element;
};
}
}));
});
inject(function($compile, $rootScope) {
var element = jqLite('<div>before<div transclude></div>after</div>').contents();
expect(element.length).toEqual(3);
expect(nodeName_(element[1])).toBe('DIV');
$compile(element)($rootScope);
expect(nodeName_(element[1])).toBe('#comment');
expect(nodeName_(comment)).toBe('#comment');
});
});
});
});

0 comments on commit 9918b74

Please sign in to comment.