"Controller as" syntax - not a good idea

19,560 views
Skip to first unread message

Ben Clinkinbeard

unread,
May 23, 2013, 9:20:08 PM5/23/13
to ang...@googlegroups.com
Exposing your entire controller to your views is bad practice IMO. $scope is a great way to mimic a presentation model/view model/whatever you want to call it while keeping the controller itself focused on logic. Especially considering the fact that exposing the whole controller was already possible via $scope.ctrl = this, I really don't get why this was added. Its existence will be seen by many devs as a recommendation for use. Angular is great, but it's demos and docs already have a reputation for encouraging/showing bad practices not appropriate for real world development. This feature will only increase that perception.

Gonto

unread,
May 23, 2013, 11:40:45 PM5/23/13
to ang...@googlegroups.com
I completely agree with this.

I see the scope as a big "ViewModel". 

The view should observe the Model through the ViewModel. The View shouldn't observe the controller. Also exposing the controller itself, though controlled (If you don't set a variable as this, it's not exposed), I don't think it's the nicest way to do this.

Why was this added?

Sam Lin

unread,
May 26, 2013, 3:49:11 PM5/26/13
to ang...@googlegroups.com
I guess AngularJS is trying to create something make new coming developers feel like there is nothing new in AngularJS. $scope is something new. 

Tony Polinelli

unread,
May 26, 2013, 6:06:21 PM5/26/13
to ang...@googlegroups.com
here's a good video explaining the feature: http://www.youtube.com/watch?v=tTihyXaz4Bo
 
im undecided. I do like the concept of having a ViewModel  ($scope) as the container for all models, its a good separation. 

but in an mvc way of thinking, the controller should handle events - ng-click for example - from the view. So the direct connection seems to make sense. Defining event handlers on the $scope does feel weird for me. 

In practice 90% of the stuff in my controllers are defined on the $scope anyways, and the rest is local variables (helper functions etc) which would still remain private with this change. The more im thinking about it this might be a logical step forward. 






--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Tony Polinelli
http://touchmypixel.com

Arturo Hernandez

unread,
May 26, 2013, 8:23:06 PM5/26/13
to ang...@googlegroups.com


On Thursday, May 23, 2013 8:20:08 PM UTC-5, Ben Clinkinbeard wrote:
Exposing your entire controller to your views is bad practice IMO. $scope is a great way to mimic a presentation model/view model/whatever you want to call it while keeping the controller itself focused on logic. Especially considering the fact that exposing the whole controller was already possible via $scope.ctrl = this, I really don't get why this was added. Its existence will be seen by many devs as a recommendation for use. Angular is great, but it's demos and docs already have a reputation for encouraging/showing bad practices not appropriate for real world development. This feature will only increase that perception.

You don't like "$scope.ctrl = this", but I don't see any direct argument against "Controller as". I know both are being added as an alternative, but I just wanted to point out the difference.

ben.clin...@gmail.com

unread,
May 26, 2013, 9:33:14 PM5/26/13
to ang...@googlegroups.com
What difference?

Tony Polinelli

unread,
May 27, 2013, 1:59:44 PM5/27/13
to ang...@googlegroups.com
This is a pretty big change. I'd like to see a blogpost about it by one of the core developers- explaining their views/thinking. 


On Sun, May 26, 2013 at 6:33 PM, ben.clin...@gmail.com <ben.clin...@gmail.com> wrote:
What difference?

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Arturo Hernandez

unread,
May 27, 2013, 2:41:46 PM5/27/13
to ang...@googlegroups.com
On Sunday, May 26, 2013 8:33:14 PM UTC-5, Ben Clinkinbeard wrote:
What difference?

Do you see how $scope could have been replaced with "this" without adding the "Controller as" syntax? 

Tony Polinelli

unread,
May 27, 2013, 2:47:46 PM5/27/13
to ang...@googlegroups.com
There doesn't seem to be much difference. As ben was saying it's just that the new syntax is suggesting that its a good idea (maybe it is). It was possible before, but just because you 'can' do something doesn't mean that you should. I'd like to hear a comment on the thoughts behind this - is it recommended practice? 


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Arturo Hernandez

unread,
May 27, 2013, 2:56:06 PM5/27/13
to ang...@googlegroups.com, to...@touchmypixel.com


On Monday, May 27, 2013 1:47:46 PM UTC-5, Tony Polinelli wrote:
There doesn't seem to be much difference. As ben was saying it's just that the new syntax is suggesting that its a good idea (maybe it is). It was possible before, but just because you 'can' do something doesn't mean that you should. I'd like to hear a comment on the thoughts behind this - is it recommended practice?

It may seem like a small difference but it sounds like the complaint is about how "Controller as" was implemented, not that "Controller as" was a bad idea in itself.

ben.clin...@gmail.com

unread,
May 27, 2013, 3:58:58 PM5/27/13
to ang...@googlegroups.com, to...@touchmypixel.com
Do you see how $scope could have been replaced with "this" without adding the "Controller as" syntax? 

Yes, from the standpoint of the view and how it accesses controller members, you can mimic the "Controller as" behavior today by doing $scope.ctrl = this in the controller.

It may seem like a small difference but it sounds like the complaint is about how "Controller as" was implemented, not that "Controller as" was a bad idea in itself.

I actually do think it's a bad idea, but others disagree which is fine. As a result I've evolved my argument. :) Since the functionality is possible without the new syntax I am looking for a justification of the new syntax.


--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/84selECbp1I/unsubscribe?hl=en-US.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Mike Alsup

unread,
May 27, 2013, 9:04:06 PM5/27/13
to ang...@googlegroups.com
"$scope.ctrl = this" does not offer the same functionality as the "as" syntax.  With "as" you can target a specific controller in your templates; that's not possible with $scope.  



--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

ben.clin...@gmail.com

unread,
May 27, 2013, 9:36:46 PM5/27/13
to ang...@googlegroups.com
Like a controller other than the one you're "in"? That's an even worse idea...

Mike Alsup

unread,
May 27, 2013, 9:57:07 PM5/27/13
to ang...@googlegroups.com
When nesting controllers you're "in" more than one, but without "as" there is no way to specify an outer controller.




On Mon, May 27, 2013 at 9:36 PM, ben.clin...@gmail.com <ben.clin...@gmail.com> wrote:
Like a controller other than the one you're "in"? That's an even worse idea...

--

ben.clin...@gmail.com

unread,
May 27, 2013, 10:09:19 PM5/27/13
to ang...@googlegroups.com
Yea, your view/template really shouldn't be reaching out to choose a specific controller to interact with. I realize we're getting into architecture recommendations again that I said I would avoid, but I find it really hard to believe that anyone thinks it is a good idea for a view to be picking and choosing where it pulls data or methods from.

I can see this is a losing battle though. Apparently the Angular community (or at least the portion active here) desires maximum API flexibility rather than opinionated focus. It is what it is, but I find it disappointing.

mlegenhausen

unread,
May 28, 2013, 1:13:39 PM5/28/13
to ang...@googlegroups.com
Especially for beginners I find the Controller as approach much more transparent, cause the $scope magic can be really confusion. One of the pitfalls is when working with nested directives that have isolated scopes, where you need to call the $parent scope which is not obvious in most of the cases. I think there is no yes or no for this approach, again "it depends" where to use it and where not.

Andy Joslin

unread,
May 28, 2013, 3:37:05 PM5/28/13
to ang...@googlegroups.com
Why is the change good?

- It makes it obvious when you have mutliple controllers which controller you are accessing at any time.
<div ng-controller="HouseCtrl as house">
  <div ng-controller="RoomCtrl as room">
    <div ng-controller="TableCtrl as table">
      The house is {{house.woah}}.  The room is {{room.groovy}}.  The table is {{table.fabulous}}, AND {{table.woah}}!
    </div>
  </div>
</div>

- It's easier for new users

- CoffeeScript and TypeScript friendliness (though I don't use these, many do)

- Isolate scope losing primitives are automatically fixed this way, without going to extra trouble of putting it in an object or doing ugly $parent-ness :-).

Broken:
<div ng-controller="MyCtrl">
  <input ng-model="someValue">
  <div ng-repeat="i in list">
    <input ng-model="someValue"> <!-- broken due to ng-repeat scope -->
  </div>
</div>

Working:
<div ng-controller="MyCtrl as my">
  <input ng-model="my.someValue">
  <div ng-repeat="number in my.list">
    <input ng-model="my.someValue">
  </div>
</div>

Why is the change bad?

- It is bad to expose the controller to the view directly.  Instead it is better to do it through a scope.
Because .. why?  Is the "this" way less coupled, and less "seperate" from the control somehow? No... Your view and controller data are immensely coupled no matter how you do it.

in the end, we are doing almost the same thing as before except using normal Javascript concepts like "this" :-).  And $scope is still there when you need it (which you will).

Alan Klement

unread,
May 29, 2013, 8:05:07 AM5/29/13
to ang...@googlegroups.com

A few things for everyone to consider.

  • Everyone has a different interpretation of what good design and 'best practices' are. This argument shouldn't be used for / against a feature.
  • Your entire controller is not exposed (if I understand correctly). Don't use the 'this' in syntax 'this.mVariable' to keep methods & data encapsulated.
  • The syntax 'Ctrl as myCtrl' leads to more explicit code (esp. in the case) as someone else has mentioned here before. Explicit > implicit.
  • As Lindquist points out in the video, it is more ECMA 6 - like. As an experienced OO programmer, exposing data in this fashion feels very at home. I think other OO programmers moving to Angular / JS will instantly get it.
  • The existing way still works and (correct me if I'm wrong) even with the new syntax, you can still inject $scope and work that way.
  • Promoting an easier what to work with nested controllers and segregate data will help contribute to more modular designs.
  • As Lindquist also points out, you won't run into the issue of accidentally manipulating primitives. 
Again, the argument of it's not 'good design' isn't enough for me - simply because everyone has a different idea of was 'good design' is.

Justin Russell

unread,
May 29, 2013, 9:24:32 AM5/29/13
to ang...@googlegroups.com
It seems odd to me that there would be essentially two flavors of controllers, those that export functionality through $scope and those that are aware they will be used as a constructor and tack items onto `this`. It looks to me like you'd have to jump through hoops (this.foo = $scope.foo = ...) to have a controller that was agnostic to how it was being used in your view, yes? If you're looking to avoid confusion for beginners... wouldn't it be best to have a single way of exporting functionality from your controller (or if you like, having a single way of "providing glue" for your view)?

Personally I don't care which flavor we go with but it would be nice to have a standard.

Also, I'm not sure what the primary motivating factor for "controller as" was, though I suspect it has something to do with the thousand and one threads on this list having to do with confusion over variables getting clobbered in nested scopes (i.e. not using "the dot"), but having introduced a number of devs to angular in the past months (and one being completely new to JS) I can say for my very limited sample size the concept of $scope was fairly easily grokked. If you're worried about making newbies scratch their heads... well, I'm not sure how much value you're going to get out of trading prototypal inheritance issues for "this" issues.

As a side note, I'm curious if the angular devs considered having an explicit scope reference in the view rather than an instance of the controller. E.g. something like:

<div ng-controller="HouseCtrl over $houseScope">
  {{$houseScope.streetAddress}}
</div>

Forces "the dot", preserves the notion of a view model, avoids fickle `this` references in async controller methods, makes it clear which scope in the chain you want to be getting `streetAddress` from.


----------------------------------------------------------------


--

Matthieu Larcher

unread,
May 29, 2013, 11:46:45 AM5/29/13
to ang...@googlegroups.com


On Wednesday, May 29, 2013 2:05:07 PM UTC+2, Alan Klement wrote:
  • Your entire controller is not exposed (if I understand correctly). Don't use the 'this' in syntax 'this.mVariable' to keep methods & data encapsulated.
 How would you go about handling unit-tests with those private variables then ?

Right now I don't see how we could achieve all the same things as before with the new proposed behaviour (including isolating internal controller methods/properties from exposed ones while still being able to test them), and I see no real benefit from straying away from the protoypal inheritance.
There's a saying that says "if it ain't broken, don't fix it" ;)

Jon Rimmer

unread,
May 29, 2013, 12:31:37 PM5/29/13
to ang...@googlegroups.com
Your unit tests should only test the public interface of your controllers, they shouldn't be concerned with their internals. That's what unit tests are for: a complete, testable description of the interface that a component provides to other components. That way, you can change the internals and use the unit tests to verify that it still provides the correct public interface. Any bug in your private implementation must, by definition, be reproducible via some appropriate test on a public method, otherwise the implementation code is useless, and should be removed, because it isn't doing anything that has any external effect.

If you still find that you have private methods within your controllers that you would prefer to test individually, it's probably a sign that you have too much complexity within your controller, and you should look to separate it into additional classes/services. You should try to keep your controllers as simple as possible: treat them as simple, self-describing containers for the current state of your view and hooks for actions, rather than complicated machines that work by manipulating an external object (the $scope).

Rob McDiarmid

unread,
May 30, 2013, 6:54:23 PM5/30/13
to ang...@googlegroups.com
This new feature makes it extremely easy and elegant to integrate AngularJS with TypeScript! Way to go angular Team.

Guillaume Lecomte

unread,
Jun 14, 2013, 3:19:12 PM6/14/13
to ang...@googlegroups.com
Doesn't that feature need a way to inject a controllerScope in the controller (a scope where this is the controller) to be able to watch members agnosticly of the alias defined in the view to be complete? Or provdide a way to mixin that scope in the controller?

Guillaume Lecomte

unread,
Jun 14, 2013, 3:22:13 PM6/14/13
to ang...@googlegroups.com
When I think about it a simple $watch service could be enough

Thomas Pons

unread,
Sep 7, 2013, 7:30:31 PM9/7/13
to ang...@googlegroups.com
The question is : why we need "this" ? $scope is good if you want some controller you got $rootScope ... or just inject modules into modules ...

I don't understand why the view can reference the controller instance it's like an anti pattern ... i think ... IMHO

David Chase

unread,
Sep 9, 2013, 10:50:03 PM9/9/13
to ang...@googlegroups.com
Im not sure how the new feature "controller as" is a bad idea... you yourself stated that angular has "$scope.ctrl = this" well the controller as syntax is the "official" way of writing "$scope.ctrl = this"
its a more declarative way of telling any developer where the methods or variables values are coming from... enforcing dot syntax instead of single primitives so {{myctrl.name}} vs {{name}} so again to reiterate before 1.2 or really before 1.1.5 when you had ng-controller="MainCtrl" in order to publish to current scope as an instance you had to do something like "$scope.mainCtrl = this" then nested within the ng-controller you could do ng-click="mainCtrl.hello()" instead of ng-click="hello()" referred inside of the controller method as this.hello = function(){}; same can now be achieved with ng-controller="MainCtrl as mainCtrl" and do ng-click="mainCtrl.hello()" without the need to return $scope.mainCtrl = this, to create an instance of the controller on the scope.

the whole purpose of a controller in angular is to augment the scope or setup an initial state.

and even if you don't alias the controller name you can access all of the properties & methods via $scope.this.someMethod or $scope.this.someName.



On Thursday, May 23, 2013 9:20:08 PM UTC-4, Ben Clinkinbeard wrote:

Diego Vilar

unread,
Sep 20, 2013, 4:18:48 AM9/20/13
to ang...@googlegroups.com
I agree having two ways of exposing data/behavior to the view is confusing and leads do destandardization.

I have been struggling with both options, trying to decide which one is best. Both have pros and cons, and I think that neither is ideal as of right now, meaning that both ways do lack some important features.

By using the $scope approach, we do abide more to MVVM, exposing to the view only what really needs to be exposed. The isolated scope problem on directives (such as ngRepeat) is actually a problem of the directive engine (not the $scope paradigm), which should handle this automagically, though I do realize it's hard to come up with a generic solution for this. On the other hand, defining data/behavior on the $scope does make it hard to extend it with more specialized implementations since we're attaching directly to an instance, not to a prototype. Polymorphism becomes difficult that way.

Say I have a view that can be used by both a BasicController and a SpecializedController. How do I extend BasicController's definition if it doesn't actually have any, because we basically defined methods and properties inside the BasicController's constructor and attached them to $scope instead of the controller prototype or instance?

Using a more OO approach, this is easily achieved. BasicController's constructor defines properties on it's instance and we attach methods to BasicController's prototype, making it easily extendable.and promoting code reuse. BUT, then, there is this new dilemma: how do I take advantage of Angular's Injector inside my controller's methods? The injector injects services into the controller's constructors, not it's methods. I can easily solve this by saving references to those services as instance properties (this._$window, for instance) and this making it available to methods, which would be actually a nice OO way of doing it. But now I'm exposing even more stuff to the world (view and whoever gets a hold of the controller's instance), although this is actually a Javascript limitation (not having private members).

There are a lot more cons/pros to both approaches, and some are actually consequences of the way Javascript was designed. But to be honest, I do find the OO approach more powerful when you're dealing with more complex applications, with many views and the need to inherit/extend controllers. And as a plus, it does make it easier to work with TypeScript.

Diego Vilar

unread,
Sep 20, 2013, 4:25:59 AM9/20/13
to ang...@googlegroups.com
To the people advocating that the "Controller as" approach makes it easier to reference parent controllers, well, I do believe you shouldn't do that. A view should only interact with it's controller. Those two are the ones coupled. Any interaction with the outside should be handled my a method on the controller, or you'll end up coupling your view with other controllers (never a good practice). If you do need one controller to interact with another, there are two "right" ways: 1) use a service; 2) use messages.

Well, at least that's what I do see as "good practices" having encapsulation and decoupling in mind.

Jason Berk

unread,
Sep 23, 2013, 1:36:16 PM9/23/13
to ang...@googlegroups.com
"If you're looking to avoid confusion for beginners... wouldn't it be best to have a single way of exporting functionality from your controller (or if you like, having a single way of "providing glue" for your view)?

Personally I don't care which flavor we go with but it would be nice to have a standard."

- hallelujah.....what a novel concept :-)  I *love* angular, but it's difficult enough to learn all it's moving parts...let alone the multiple syntax for each thing.

Tony pee

unread,
Sep 24, 2013, 12:45:44 AM9/24/13
to ang...@googlegroups.com
I like the controller 'as' syntax. But i like it better when i use the name 'ViewModel' rather than Controller. When i think of it as a ViewModel, which is attached to the scope, rather than a controller which should be decorating the ViewModel (scope?) as in the old syntax.. it makes more sense. You are directly building your ViewModel.. which is great. How it is glued into the view is via a scope.. technicalities that you dont *really* need to know at first. Its semantics.. but maybe somewhat important conceptuallly

 



For more options, visit https://groups.google.com/groups/opt_out.



--
Tony Polinelli

mattias w

unread,
Nov 19, 2013, 7:45:03 AM11/19/13
to ang...@googlegroups.com
Thank you for adding "controller as". I never liked JavaScript, too fault-sensitive for me (WebStorm might change that). Now I can combine a productive program language like TypeScript with an even nicer web-framework.

Everything I have done sofar has worked!

Кошелев Иван

unread,
Dec 10, 2013, 8:11:04 AM12/10/13
to ang...@googlegroups.com
Examined the idea cautiously, and I now use it in a real app with Typescript. So far, I don't see any problem with it. Any inheriting scope that relies on {{propName}} attached by ctrlName on an ancestor scope can still rely on {{ctrlName.propName}}. Alternatively, if I want {{propName}} without knowing who supplies it - I can still explicitly attach it to scope in my controller (same as I would "$scope.ctrl = this" before, but this is needed a lot less often then "$scope.ctrl = this"), and explicit is always better then implicit in production.

Kay

unread,
Dec 17, 2013, 1:29:05 PM12/17/13
to ang...@googlegroups.com
The "controller-as" syntax raised some inconsistencies to the framework's design decisions which, I believe, need to be addressed or at least clarified.

One of the issues is that special models that are generated by the framework, eg. item in ng-repeat="item in main.items", or form.email.$valid in <form name="form"><input name="email" type="email"></form> are still being put under $scope regardless of the "controller-as" syntax, so conceptually there is now two competing model containers storing interrelated information that should really be integrated as a single whole. However you also probably won't wanna hook these special models under main (or other controller instance alias) because ng-repeat="main.item in main.items" or main.form.email.$valid are just way too verbose and stupid.

It seems to me that while the "controller-as" syntax (btw, we need a better name than that to refer to this feature...) solves a certain problem, ie. the primitive type binding issue, it's hardly a beneficial addition to the integrity of the framework, and is probably introduced majorly for the sake of AngularDart or some Google coding styles.

Kay

unread,
Dec 17, 2013, 2:20:14 PM12/17/13
to ang...@googlegroups.com
Just checked it again and apparently the form example has since been fixed to allow the usage of main.form.email.$valid.

Кошелев Иван

unread,
Dec 18, 2013, 2:34:37 PM12/18/13
to ang...@googlegroups.com
You picked the same part of Angular that gave me the most doubts when I was considering this syntax and Angular in general, which is not a coincidence, I think. And you do have a point - there is an inconsistency in this particular part. What nicely illustrates the inconsistency, is the fact that our production apps use "novalidate" attribute on most forms, because otherwise normal browser validation interferes with ours. I first thought about the form problem when I considered that it just feels wrong to set up validation rules in views, when a View should not know about Model. We use form validation attributes of HTML because we are used to it, but that is not MVC \ MVVM. The right solution, of the top of my head, would be a syntax like <form ng-form="mainCtrl.form">....</form>, and I would also like to be able to do form.inputName.addValidationRule("ng-required", function(){ return requiredIndicator1 || requiredIndicator2 ;}); inside that controller initialization function.

Another lesson hard learned for me is the following (names are generalized): just today I was working on a controller, because api.updateEntityPart(bizData, $scope.entityId); failed The problem was - the entityId was undefined, because it was named $scope.entityFullNameId by the controller that attached it (a recent rename). In order to find it and verify the bug, I had to breakpoint my Chrome and examine the whole $scope chain, some 4 or 5 parents long. had it been attached as  $scope.entityCtrl.entityId - and I would know where to look the moment I saw it. Better yet, the bug could be avoided altogether, since a search for "$scope.entityCtrl" would show up any controllers dependent on it in the inheritance chain. This approach allows us to easily detect external dependencies on a controller and work out its expected interface.

As a final suggestion - suppose someone deleted $scope.entityFullNameId = x; from its controller altogether - we would suddenly be left with a controller dependent on a missing part with no clue as to who was supposed to provide it in the first place (short of restoring our version from yesterday and examining it). 

Nick Manning

unread,
Jan 18, 2014, 7:41:13 PM1/18/14
to ang...@googlegroups.com
Hi...here is a relevant stackoverflow question, possibly showing that "ctrl as" syntax is the best solution if someone wants to add angularJS over an already existing javascript program---

Guillaume Lecomte

unread,
Feb 20, 2014, 4:16:52 PM2/20/14
to ang...@googlegroups.com
Sorry to bring that back but am I the only one who see a design problem here? 
We define an alias in the view/template ( MyCtrl as controller ), if we want to watch a variable in the (controller) scope from the controller, we need to know the alias we defined in the template ($scope.$watch('controller.varname', ...), 
it's not DRY, it generates coupling and prevent reusing several times the same controller (nested).

I'm suggesting a $controllerScope injectable (a $scope 'scoped' on the controller) to solve that, does anyone else want something like that?

Tony pee

unread,
Feb 20, 2014, 5:12:52 PM2/20/14
to ang...@googlegroups.com
I thought the same thing. Im not sure about the $controllerScope idea, seems complex, and duplicates a lot of functionality Basically making the container scope useless - or going back to the days where the controller IS the scope. 

I'd suggest that we really just need a reference to the controller that doesnt rely on the alias, as that has coupling issues as you stated. 

having a $ctrl variable created on the $scope, which always references the controller would mean you can do:

$scope.$watch('$crtl.MyVar', function() {
    console.log('x');
})

It seems a handy way to access the controller in general id think

--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/groups/opt_out.



--
Tony Polinelli

kosh...@gmail.com

unread,
Feb 20, 2014, 5:02:00 PM2/20/14
to ang...@googlegroups.com
>>$scope.$watch('controller.varname', ...)
Valid point. But in development I'm yet to encounter a situation where this would pose a problem. A lot more often I’m found in a situation where controller A uses a variable on the scope that it did not define and I am forced to go look for its defining controller by simple text  search for its name.

Plus, if you have a variable that will be used somewhere down the scope inheritance chain, it is already a good practice to declare it on an object attached to a scope as opposed to the scope itself, to avoid accidental overshadowing if you write into it. 
--
You received this message because you are subscribed to a topic in the Google Groups "AngularJS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/angular/84selECbp1I/unsubscribe.
To unsubscribe from this group and all its topics, send an email to angular+u...@googlegroups.com.

Guillaume Lecomte

unread,
Feb 21, 2014, 3:57:45 PM2/21/14
to ang...@googlegroups.com
Good idea, another approach could just be a $alias injectable string. Avantage is that angular can throw an error at controller initialisation if no alias is available.

Or a scope.watchController method...

(I'm not confortable using CTRL as syntax until something solve this)

Artem Saveliev

unread,
Mar 10, 2014, 3:44:28 PM3/10/14
to ang...@googlegroups.com
Comment on actual development - Angular UI's ngGrid uses string reference to data variable. They allow the use of both object reference and string name, but string name is the only one that supports data updates.
The reason is that they use $watch to watch the data. 

I just found that I can't cleanly use "controller as" together with ngGrid for that reason - my controller doesn't know what name to pass to ngGrid, as it doesn't know it's own name. There are several workarounds that I am considering, but in general this will be an issue as you can't cleanly watch the content of the controller. I really need to know the string name of the controller at the time of construction for a simple solution.

Samantha Atkins

unread,
Apr 7, 2014, 9:08:29 PM4/7/14
to ang...@googlegroups.com
I am  confused.   My understanding is that in an angular Controller 'this' refers to the controller context itself like any other constructor function where '$scope'  is current angularjs $scope/view object.  They are not the same thing.  If you define a function on 'this' and a function on '$scope' the latter can be seen by your html but not the former.  With the ridiculous javascript non-lexical exceptions on 'this' mixed in it makes for quite a confusion-party.  Then toss in that child scopes get created fairly often where your constructor 'this' is not changing across these sub-scopes.  And then there are directives.  This stuff is as clear as mud.  It really needs to be cleaned up.  

Vinay Gangoli

unread,
Apr 22, 2014, 7:07:24 PM4/22/14
to ang...@googlegroups.com
I know this is an old post, but could you elaborate further on how you could encapsulate functions to prevent them from being visible on the scope inspite of being in the controller?
I am using Typescript and cannot find an answer to hiding helper functions from the scope when using $scope=this.

Кошелев Иван

unread,
Apr 23, 2014, 5:21:12 AM4/23/14
to ang...@googlegroups.com
Vinay, you can't hide functions from the scope when using it as this, that is exactly why the "controller as" syntax comes in so handy. With that syntax, initialization of your controller goes as foollow:

"<div ng-controller="CountController as CountCtrl" >...</div>" roughly the following happens "$scope.CountCtrl = new CountController(...dependencies)"

With that, the return object of the constructor function (normally the 'this') will be available on the on the $scope.CountCtrl var, like this:
<div ng-controller="CountController as CountCtrl" >
<p>The count is {{CountCtrl.counter}}</p>
</div>

The beauty of it is:
- Your controller does not even need to know of the $scope - an example later showcases this (CountController in the example has no dependenices at all, but i inject the $q just to showcase use of injection with this syntax). This allows you to reuse controllers from the world of angular in, say, NodeJS and bring non-angular controllers into your code with few-to-non modifications needed. You are creating it in a way that is more universal across all of JS, not specific to one framework.
- Inheritance of $scope is more specific. You can have two of those controllers in one chain of $scope inheritance by different names and they will not overshadow one another (see example later). Calls to functions will be more explicit and much easier to read, once you create a structure of more then two nested controllers. 


Here is the plunker that showcases using that transpiled AngularJS TypeScript controller use

Vinay Gangoli

unread,
Apr 23, 2014, 1:43:14 PM4/23/14
to ang...@googlegroups.com
Thanks for the reply! The examples are very clear and I especially like the handling of nested controllers.

I guess my concern here is I would be able to do controller.$q.anyExposedProp from the view which I would like to prevent.
Is there any way to achieve this in Typescript?

Кошелев Иван

unread,
Apr 24, 2014, 7:20:37 AM4/24/14
to ang...@googlegroups.com
Vinay, I see. In TypeScrpit when you use 'class' keyword there is no way to make the generated properties JS private, even if you use the 'private' TS keyword. The reason for that is described here http://typescript.codeplex.com/discussions/397651 . As they describe - the problem is about JS inheritance overall and the fact that TS 'private' keyword behaves like 'protected' keyword of languages with traditional inheritance. The problem is more about prototypical inheritance, so discussing it here would be of-topic, IMHO.

In consolation, I can say I never had any problems of that sort in projects with Controllers like
constructor(public api: ApiService, public $modalInstance: ng.IModalInstance, public work: IWorkVM, public $rootScope: ng.IScope, public $q: ng.IQService, public $timeout: ng.ITimeoutService) {...}

If you have some specific case where that problem occurs, maybe you could email me a description of it to koshelew at gmail com ?

Tony pee

unread,
May 5, 2014, 6:26:46 PM5/5/14
to ang...@googlegroups.com
Im wondering what original reasons for not having the controller *be* the scope were (like it originally was). Is it because of the need for scope inheritance? 

Using 'controller as' the scope is barely referenced, and so scope inheritance isnt useful to the developer anyway. services are used for inter-controller sharing anyway. If removing the inheritance simplified the system, then could the controller *Be* the scope again?

My thinking is that, if inheritance is removed, and a tree is built using this.parent (for events - as is currently, and is like the DOM for example) then the controller could just extend a scope class. 

'Controller as' is not really needed then, but could just be an attribute referencing *this* if you wanted that style in the view. 







--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.

To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.



--
Tony Polinelli

Georgii Dolzhykov

unread,
May 6, 2014, 11:19:21 AM5/6/14
to ang...@googlegroups.com
Here is another issue with this feature:

http://stackoverflow.com/q/23496850/76173 (“controller as” vs isolate scope)

Tony pee

unread,
May 7, 2014, 1:48:10 AM5/7/14
to Кошелев Иван, ang...@googlegroups.com

Thanks for your reply. Makes sense. I wasn't thinking of the case of multiple controllers, as much, in which case isolation is better. 

On 6 May 2014 03:12, Кошелев Иван <kosh...@gmail.com> wrote:
Having controller be the scope would bring a lot of problems into the picture - you would only be able to use inheritance rather then composition to construct you scope objects, which would essentially cripple a dynamically typed language like JS. 

i dont think inheritance is necessarily bad. as a (possibly terrible) example we can hack it to inherit the scope: http://plnkr.co/edit/9zc6yWHid4mJSwzUGUOe?p=preview. This would lead to some serious naming clashes however - although, same goes for controllerAs however - just to a lesser degree. (if your 'as' var clashes)

Right now Angular mostly relies on mixins type of composition (each controller adds methods and properties directly to the scope object). "Controller as" gives you a shortcut to more classical composition (controller encapsulates all the needed functionality and becomes a well isolated part of the scope object). To understand why this is better - consider this two situations: 
1.) You have an element like <div ng-controller="Ctrl1" ng-directive1 ng-directive2 >...</div>, where both directives have controllers of their own. No single controller can become the whole scope. You can either have them all mix into the same scope, or, as i prefer, attach themselves to it. The second way is just much cleaner and less prone to naming collisions. 

agreed. In the case if multiple controllers, it does make much more sense to isolate. This to me is the best reason for controllerAs.

 
2.) Think broader about controllers then just Angular controllers. Think of the scope as just another dependency (an optional one at that). As i said earlier,  "This allows you to reuse controllers from the world of Angular in, say, NodeJS and bring non-angular controllers into your code with few-to-non modifications needed. You are creating it in a way that is more universal across all of JS, not specific to one framework." With that, you usually also get a much cleaner Separation of Concerns.

As for the barely referenced part - there isn't much to reference beyond
" '<div ng-controller="CountController as CountCtrl" >...</div>' roughly the following happens '$scope.CountCtrl = new CountController(...dependencies)' "


yup. makes sense. Im still just annoyed by 



--
Tony Polinelli

Gediminas Bukauskas

unread,
Jul 30, 2014, 1:23:31 AM7/30/14
to ang...@googlegroups.com
Using this instead of $scope would make problems writing unit tests: writing scenario in Jasmine I can to create new scope cutting dependencies that aren't interest in current test. I have studied many articles about "controller as ..." but found nothing about testing. Can anybody write short test sample where calling $http is replaced with stub? Controller and model are tightly connected using "this", Dependency Injection stops working. Is it true?

Gediminas
Message has been deleted

Samuel Bach

unread,
Aug 1, 2014, 7:30:19 AM8/1/14
to ang...@googlegroups.com
Why not just do this in the controller:

app.controller('MyCtrl', function($scope) {
  $scope.var1 = "this is var1";
  $scope.var2 = "this is var2";
  this.scope = $scope;
});.


So that we can do the following in the template:

<div ng-controller="MyCtrl as my">
    <div> 
        {{my.scope.var1}}
    </div>      
    <div ng-controller="OtherCtrl as other">          
        {{my.scope.var1}}
        {{other.scope.someVar}}
    </div>
</div>


This would give us the benefits from both sides: 
  1. Use alias'ing in view (for nested controllers)
  2. Actually work on the $scope-object (we still have $apply, $watch etc and dont have to change testing)
The only catch that I can see so far is that I have to write the scope variable everytime, which is a bit ugly. 
What do you think about that? Does this break something that I dont know of? (Im still a angular novice)

safiyu dheen

unread,
Nov 12, 2014, 11:39:51 AM11/12/14
to ang...@googlegroups.com
I was able to achieve unit testing using karma chai and mocha.. I didn't get what impossibilities were you trying to convey.. Can you please elaborate as I am curious to know.

safiyu dheen

unread,
Nov 12, 2014, 11:40:14 AM11/12/14
to ang...@googlegroups.com

safiyu dheen

unread,
Nov 12, 2014, 11:51:04 AM11/12/14
to ang...@googlegroups.com

safiyu dheen

unread,
Nov 12, 2014, 11:51:06 AM11/12/14
to ang...@googlegroups.com

safiyu dheen

unread,
Nov 12, 2014, 11:51:08 AM11/12/14
to ang...@googlegroups.com

safiyu dheen

unread,
Nov 12, 2014, 11:54:22 AM11/12/14
to ang...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages