Skip to content

Commit 772e32c

Browse files
committed
change ng:controller to create new scope hence allow nesting
1 parent c30807d commit 772e32c

3 files changed

Lines changed: 56 additions & 23 deletions

File tree

src/Compiler.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,42 @@ function Template(priority) {
99
this.children = [];
1010
this.inits = [];
1111
this.priority = priority;
12+
this.newScope = false;
1213
}
1314

1415
Template.prototype = {
1516
init: function(element, scope) {
1617
var inits = {};
17-
this.collectInits(element, inits);
18+
this.collectInits(element, inits, scope);
1819
foreachSorted(inits, function(queue){
19-
foreach(queue, function(fn){
20-
fn(scope);
21-
});
20+
foreach(queue, function(fn) {fn();});
2221
});
2322
},
2423

25-
collectInits: function(element, inits) {
26-
var queue = inits[this.priority];
24+
collectInits: function(element, inits, scope) {
25+
var queue = inits[this.priority], childScope = scope;
2726
if (!queue) {
2827
inits[this.priority] = queue = [];
2928
}
3029
element = jqLite(element);
30+
if (this.newScope) {
31+
childScope = createScope(scope);
32+
scope.$onEval(childScope.$eval);
33+
}
3134
foreach(this.inits, function(fn) {
32-
queue.push(function(scope) {
33-
scope.$tryEval(function(){
34-
return fn.call(scope, element);
35+
queue.push(function() {
36+
childScope.$tryEval(function(){
37+
return fn.call(childScope, element);
3538
}, element);
3639
});
3740
});
38-
3941
var i,
4042
childNodes = element[0].childNodes,
4143
children = this.children,
4244
paths = this.paths,
4345
length = paths.length;
4446
for (i = 0; i < length; i++) {
45-
children[i].collectInits(childNodes[paths[i]], inits);
47+
children[i].collectInits(childNodes[paths[i]], inits, childScope);
4648
}
4749
},
4850

@@ -121,7 +123,8 @@ Compiler.prototype = {
121123
element:function(type) {return jqLite(document.createElement(type));},
122124
text:function(text) {return jqLite(document.createTextNode(text));},
123125
descend: function(value){ if(isDefined(value)) descend = value; return descend;},
124-
directives: function(value){ if(isDefined(value)) directives = value; return directives;}
126+
directives: function(value){ if(isDefined(value)) directives = value; return directives;},
127+
scope: function(value){ if(isDefined(value)) template.newScope = template.newScope || value ; return template.newScope;}
125128
};
126129
try {
127130
priority = element.attr('ng:eval-order') || priority || 0;

src/directives.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ angularDirective("ng:init", function(expression){
55
});
66

77
angularDirective("ng:controller", function(expression){
8+
this.scope(true);
89
return function(element){
910
var controller = getter(window, expression, true) || getter(this, expression, true);
1011
if (!controller)
1112
throw "Can not find '"+expression+"' controller.";
1213
if (!isFunction(controller))
1314
throw "Reference '"+expression+"' is not a class.";
1415
this.$become(controller);
15-
(this.init || noop)();
1616
};
1717
});
1818

test/directivesSpec.js

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,23 +254,53 @@ describe("directives", function(){
254254
});
255255

256256
describe('ng:controller', function(){
257-
it('should bind', function(){
258-
window.Greeter = function(){
257+
258+
var temp;
259+
260+
beforeEach(function(){
261+
temp = window.temp = {};
262+
temp.Greeter = function(){
263+
this.$root.greeter = this;
259264
this.greeting = 'hello';
265+
this.suffix = '!';
260266
};
261-
window.Greeter.prototype = {
262-
init: function(){
263-
this.suffix = '!';
264-
},
267+
temp.Greeter.prototype = {
265268
greet: function(name) {
266269
return this.greeting + ' ' + name + this.suffix;
267270
}
268271
};
269-
var scope = compile('<div ng:controller="Greeter"></div>');
270-
expect(scope.greeting).toEqual('hello');
271-
expect(scope.greet('misko')).toEqual('hello misko!');
272-
window.Greeter = undefined;
273272
});
273+
274+
afterEach(function(){
275+
window.temp = undefined;
276+
});
277+
278+
it('should bind', function(){
279+
var scope = compile('<div ng:controller="temp.Greeter"></div>');
280+
expect(scope.greeter.greeting).toEqual('hello');
281+
expect(scope.greeter.greet('misko')).toEqual('hello misko!');
282+
});
283+
284+
it('should support nested controllers', function(){
285+
temp.ChildGreeter = function() {
286+
this.greeting = 'hey';
287+
this.$root.childGreeter = this;
288+
};
289+
temp.ChildGreeter.prototype = {
290+
greet: function() {
291+
return this.greeting + ' dude' + this.suffix;
292+
}
293+
};
294+
var scope = compile('<div ng:controller="temp.Greeter"><div ng:controller="temp.ChildGreeter">{{greet("misko")}}</div></div>');
295+
expect(scope.greeting).not.toBeDefined();
296+
expect(scope.greeter.greeting).toEqual('hello');
297+
expect(scope.greeter.greet('misko')).toEqual('hello misko!');
298+
expect(scope.greeter.greeting).toEqual('hello');
299+
expect(scope.childGreeter.greeting).toEqual('hey');
300+
expect(scope.childGreeter.$parent.greeting).toEqual('hello');
301+
expect(scope.$element.text()).toEqual('hey dude!');
302+
});
303+
274304
});
275305

276306
it('should eval things according to ng:eval-order', function(){

0 commit comments

Comments
 (0)