Thinking in Components
Recently, I wrote an AngularJS Structure Style Guide (incomplete) because I haven’t seen one that would allow my current project to scale. By scale, it had to extremely maintainable by being simple; reflecting what the app does without confusing new (even old, core) developers.
Personally, I found a lot of guides out there to be extremely terrible. AngularJS isn’t so bad, except for the V part which has an obnoxiously bad API.
Separation of concerns has its own tradeoffs. A lot of people don’t seem to understand this; they tend to use the Controller for everything. Even library authors instruct that way. Although library authors are not to be blamed, it seemed to have been applied in practice by everybody, and that’s not awesome.
In reality, it’s insane to let a controller do everything. Some people insist on making 2 controllers for one single *state*, and I think that’s more insane.
Both are anti-patterns.
I found this to be hard to predict and understand.
It’s more sane to think of it this way:
I’m not sure how interpret these kind of things, but here’s the idea: Let the controller just handle the main data (from whatever source, ajax or whatever), then pass the data to the directives through the view (template).
This allows us to predict the app.
Directives are awesome
Don’t limit the use of directives to jQuery, DOM manipulation, or whatever. Trust me, It’s more useful to split a building to smaller parts. It’s also easier to unit test them. Although it is arguable that using directives for everything is extremely unproductive (because of its shitty API), it seems to be the best way to go.
While we’re at it, let’s take ReactJS’s example from their documentation, Thinking In React.
Let’s separate this to 4 directives and a controller.
- ProductController (orange): Contains the entirety of the example, handles and manages the data (aka products)
- search-bar (blue): Receives all user input
- product-table (green): Displays and filters the data collection based on user input
- product-category-row (turquoise): Displays a heading for each category
- product-row (red): Displays a row for each product
Now this is unit-testable (very very easy to unit-test), because besides understanding the flow of the code, you understand which to test due to small scope of each.
Why 4 directives? My idea is to set the controller only to handle, serve the data. Then, let us separate our whole chunk to simple directives.
Here’s a sample code which properly reflects the above mock.
If possible, keep the controller to less than a hundred of lines of code.
(By scope, I do not mean $scope) This is applicable to your entire app. You may diverge from here on (actually, wherever you want to).
- MainController (green): Handles essential data for the whole app, can also be a controller for the main template. There’s usually little to no use for this (especially at first), but there can be cases when this can come in handy.
- sidebar (red): Collapsible sidebar, tempalte for the sidebar
- profile dropdown (light blue): Handles the profile dropdown
- notification (dark blue): Handles the notification dropdown, updating the nofication data
- helper (orange): Maybe a listener for the ? key presses, or spawns a modal for assistance, etc..
- Controller (brown): Your current state’s controller, handles data for the current request
At the end of the day, best practices boils down to proper programming principles; which matters most; what fits your project requirements, teams and project needs. And like what I said,
Although it is arguable that using directives for everything is extremely unproductive (because of its shitty API), it seems to be the best way to go.
Thoughts, suggestions? Feel free.