I’m scratching the surface with Angularjs, and thought I’d run a conceptual question past the fine folks of SO. This is a newbie question from a seasoned developer.
The application has dashboard requirements… a single page that surfaces stuff from many parts of the application. Different user types get different dashboards. We already have a legacy back end, so the first task is to build the dashboard to show many bits from it’s new RESTful service layer.
I’m wondering how I should conceptually think about the controllers needed to support this?
The first question is… should they be model-centric or view-centric? In other words, should they be “view-centric” controllers that have the word “Dashboard” in them? Or should they be more focused on the model elements they represent, like “Tasks”, “Contacts”, “Notifications”. Or should there be both where the dashboard controllers work with model-centric controllers?
The next question is… what level of granularity should the controllers represent? If view-centric “Dashboards” controllers, should they be “ManagerDashboardController” and “WorkerDashboardController”? If model-centric controllers, should there be controllers such as “LateTasks” & “OnTimeTasks” since I need to display them on different sections of the dashboard, with slightly different data?
I’m looking for tangible advice based on real-world experience and/or references to great links I’ve yet to find.
This is very subjective but here is my answer to your questions
should controllers be model-centric or view-centric?
It depends (as always), I always try to have small controllers for the different parts of the page.
Some parts of the page are very view-centric (typically the ones that are shared among the different views). I usually have a menuCtrl, a headerCtrl and footerCtrl. This ctrls are very coupled to those parts of the page so a make them view-centric.
The other parts of the view, the ones that are business related are much more coupled to the business rules and in extension to the model so I make those ctrls model-centric. On an account´s business app, I would probably have an accountCtrl, an ownerCtrl, and so on. By doing so I can reuse them on different views if needed (and are much easier to test)
what level of granularity should the controllers represent?
The smallest as possible. Try to have small controllers that prepare the model for different parts of the page. If you have a big controller it will be hard to test, maintain and you will probably be forced to duplicate code on different parts of your application.
advices and recomentations with controllers
Keep them small.
Avoid DOM manipulation inside of them (use directives instead).
Use the controllers just to prepare the model. whenever possible delegate all the logic of your app to services. If you do so, it won´t really matter that much if your controller is view-centric or model-centric.
As I said before this is a very subjective matter and I´m sure many people will disagree with me.
I hope this could help you.
Here are my views from developing business applications in Angular for the past 6 months:
Role of a Controller
- Initialization (loading initial data, setting options)
- Exposing variables and functions to the template through the $scope
- Application flow (through exposure of functions that can change state, or
I have found that, much like in traditional MVC frameworks, the controllers in an Angular app should really be super slim. Little if any business logic should be in the controllers, and should be instead be encapsulated in your models. I came to this conclusion after hearing the follow line from a presentation by Miško Hevery: “the purpose of the scope is to refer to the model and not be the model.” That was the most valuable and enlightening line I got from that presentation (though I recommend to watch the whole video); that line directly resulted in me slimming down my controllers by almost 50%-70%.
For example, my company has a concept of an
Order. I created a model that encapsulated all the properties of this business object, as well as its behaviours and injected them into the controllers. One business rule we had was the ability to add a
Booking (another business object) to the
Order. Originally in my controller, I had a
$scope.addBooking function that first created a new
Booking, then took the order and did a
$scope.order.bookings.push(newBooking). Instead, I moved this business logic (
addBooking function) directly into my
Order model, and in the template I could then do something like
<button ng-click="order.addBooking()">Add Booking</button> without adding a single line of code into my controller.
A lot of the code I put in my controllers when I was first starting off with angular, I found could be stripped out and placed either in my models, directives, or services (mostly the first two in my case). The remainder of the code left in my controllers almost all fell into one of the above 3 roles I listed above. It was either initialization code (e.g. firing an AJAX request to fetch data of the relevant business objects), scope assignment of objects, or scope assignment of functions that dealt with application flow (e.g.
$scope.cancel that might send you back to a different page).
Should controllers be model-centric or view-centric?
This is an interesting question, one that I haven’t thought about before. When I hear view-centric, I think of a controller that deals primarily with the view and how things are displayed. I feel there shouldn’t be any controllers that are purely view-centric, the reason being it seems a view-centric controller can probably be transformed into a directive. You mentioned view-centric controllers as being like a
Dashboard controller, which sounds like something that could definitely be made into a generic directive. Your directives should encapsulate most of your view logic, while your controllers focus on simply exposing your models to the view for consumption (back to the role of the controller). This has me thinking that controllers should more often be model-centric.
I think really the only conclusion I can come to is if a controller starts becoming too view-centric (with many variables and functions that deal primarily with the view and UI behaviour) then that is a sign that parts of your controller can be pulled out into a directive, making your controller slimmer.
So I’m actually in the process of migrating a legacy code base over to a restful based web service architecture utilizing AngularJs
Controllers are responsible for managing the data that is consumed by the view aka the webpage. My personal preference is that there is a one to one relationship between the controller and the view that it is serving. So, based on the question, Angular controllers should be more view centric. I’m sure that there are plenty of people who will disagree with me though.
If you are worried about the extensibility of this pattern, you should place your business logic and data access within Angular Services as described here. This offers you a tremendous amount of reuse of business logic operations as well as unit testability.
The specifications for Angular are changing all the time and with each new version there will be a new standard. A more view centric architecture looks appropriate for this application.
For some more complete reading on the subject I recommend checking out: