Attracted by AngularJS power and simplicity, you have chosen it for your next project. Getting started with DataBinding, Scopes and Controllers was relatively quick and easy. But what do you need to effectively bring a complex application to Production? We discuss the new Component API, from ngOnChanges to selecting different ways for components to collaborate, from choosing between Two-Way Binding and One-Way Data Flow, to "smart" vs "dumb" components, sharing recipes from our real world experience so that you can productively & reliably build a complex application out of reusable Components.
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Angular Rebooted: Components Everywhere - Carlo Bonamico, Sonia Pini - Codemotion Milan 2016
1. Angular Rebooted:
Components Everywhere
Carlo Bonamico -Sonia Pini
MILAN 25-26 NOVEMBER 2016
sonia.pini@nispro.it
carlo.bonamico@nispro.it - NIS s.r.l. - a DGS company
carlo.bonamico@gmail.com – Genova Java User Group
Twitter: @carlobonamico @nis_srl
2. Abstract
Attracted by AngularJS power and simplicity, you have chosen it for your next project.
Getting started with DataBinding, Scopes and Controllers was relatively quick and
easy...
But what do you need to effectively bring a complex application to Production?
We discuss
● the new Component API,
● lifecycle callbacks - $onChanges
● selecting different ways for components to collaborate
● choosing between Two-Way Binding and One-Way Data Flow,
● "smart" vs "dumb" components,
We ‘ll share recipes from our real world experience so that you can productively &
reliably build a complex application out of reusable Components.
3. We all love AngularJs
● Simple & Powerful
○ Two way data binding is legendary
○ Dependency Injection is awesome
○ Routing is very flexible
○ D.R.Y and reusable code made easy
○ Components/Directives FTW
○ Modular and component-driven
…
○ Testable code
We all love AngularJs
4. Real world apps are not easy
Bringing a complex application to production
requires more than quickly bind form fields:
● decoupling unrelated parts
● preventing fragility in the face of changes
● keeping collaboration effective as team grows
● avoiding performance issues
Angular gives us good tools
- but we need to use them in the right way
5. Avoiding bad practices
Often, as the application starts to grow, we see
● single large controller and HTML file per view
○ thousands of lines each
● significant repetition across views
○ same HTML fragments in many files
● “Spaghetti Binding”
○ creates dependencies between unrelated parts
Code becomes hard to navigate / risky to change
We need Software Engineering for the Frontend, too
7. What is a Component?
● Self-contained set of UI and logic
○ encapsulates a specific behaviour
○ provides an explicit API
● Since Angular 1.5, special kind of Directive with
○ UI in a template
○ Logic in a controller
○ some metadata (inputs, outputs, …)
● Makes it easier/cheaper to do a good design
○ pushing the community towards best practices
● In Angular 2, the main application construct
8. Most of the concepts that we present apply to both
Angular 1.5 & Angular 2.0
although syntax is different
9. Example App: NG Component Mail
Full Source in https://github.com/carlobonamico/angular-component-based
11. Design the Component API
Define input and output properties
● Keep naming conventions consistent
● Follow Clean Code guidelines
<component>
inputs
outputs
12. <folder-list> API and behavior
input → folder array, title, allowCreate
output → selected folder
encapsulated state and
behaviour →
current folder, select with click,
sorting, filtering
16. Why didn’t we use “=”?
The “=” qualifier means that the binding is two-way
● the <folder-list> component could even replace
the folder array with another one
○ while it’s role is just to display it
● and this change could also immediately affect
various other parts of the page which reference
the folder array in their {{}} expressions and
$watch-es
Guideline: default to “<” for component inputs
● one-way change propagation
17. Two-way bindings pros and cons
● Very effective collaboration “in the small”
○ like when all people in a room can talk to each
other to solve a problem
○ ng-model for bi-directional updates between
form inputs and model
○ a validation expression can reference several
model variables
● creates chaos “in the large”
○ think all people in the building talking to any
one else
18. How to handle <folder-list> Output?
Passing the selected folder to the MailController
which updates the message list - ideas?
● Option 1
■ $scope.$parent.currentFolder = selectedFolder
○ avoid! it makes the component non-reusable
● Option 2 - two-way binding
■ binding selectedFolder : “=”
■ <folder-list selected-folder=”mailCtrl.currentFolder”>
■ in the parent, $watch(‘currentFolder’, function(){
loadMessages(currentFolder)})
19. Making Outputs explicit with Events
Option 3 - The component
● detects when a significant user action takes place
● updates its internal state
○ e.g. track the selected folder
● updates its view
○ display the element in bold / red
● sends an event to notify the parent component
○ including relevant data (e.g. folder id / name)
● lets the parent component decide what to do then
○ e.g. retrieving a new message list
20. Sending the event in <folder-list>
● We declare an output binding with “&”
● Angular injects an emitter function in the controller
● We call it passing an Event Object including
relevant data
MailController
<folder-list>
component
21. Using the component output
Specify an expression to be executed in the parent
scope when the event is received
Parent Component Controller
FolderListController
mail-view HTML
22. Advantages
Stonger Encapsulation (isolated scope + explicit
binding)
● changing the component internal implementation
has less impact on the rest of the application
● more decoupling, less regressions
Reusability (with parametrization)
● same component used in different contexts
○ <message-list> can display either folder
messages and search results
23. Advantages
Better Collaboration
● less conflicts when team grows
● easier to test for regressions
More Clarity and Readability
● I can effectively use a component knowing only
its API (the bindings section)
● the link to other component is very clear and
explict in the HTML
24. Components all the way down
What happens if we consistently apply this pattern
across the entire application?
The application becomes...
25. A tree of collaborating Components
<mail-view>
<folder-list> <message-list>
<nav-actions><common-star>
<message-view>
<common-star>
28. Components: Smart vs Dumb
● Also called stateful
● Provides data - e.g. from http
REST clients
● May receive initial data via
route resolves
● Has knowledge of the
current state
● Is informed by stateless
components when
something needs to change
● Also called stateless
● Like a pure JavaScript
function
● It receives data via property
binding
● it focuses on rendering and
interaction without
managing business logic
● It requests state changes
through explicit events
29. Data Flow “down”: property binding
Component pass a subset of their model to children
<mail-view>
<folder-list> <message-list>
<nav-actions><common-star>
<message-view>
<common-star>
folders
messages
currentMessage
34. Advantages
If a component passes data to its children, that it
knows well, the risk of unintended side effects is low
If a component notifies its parent, the change can
potentially affect unrelated / not yet developed parts
● more explicit and controlled
● parent component can mediate and orchestrate
how the child interacts with the rest
Also, the tree is very good for performance
36. Component means Composable
There is no “right answer”, but...
● if a component becomes too big, split it into
collaborating child components
Basic Design Principles
●Low Coupling - avoid unneeded dependencies
●High Cohesion - Single Responsibility Principle
(SOLID Principle)
− separate things that change for different
reasons or at different times
In short: don’t put your socks in the fridge...
37. Single Responsibility applied
If you need to do 2 things, make 3 components
● A, B
● C that does A + B
Example
● <upload-attachment> does file browsing and calls
the UploadService HTTP client
● <attachment-list> displays the currently attached
messages
● <mail-attachments> groups the first two
38. More Component goodies
● Since Angular 1.5.3, Components can declare
"lifecycle hooks"
● $onInit()
○ one-time initialization after interconnected
components have been bound
○ https://toddmotto.com/on-init-require-object-syntax-angular
-component
● $onDestroy()
○ deallocate resources when the component is
removed from the view
○ e.g. a websocket in a chat
39. Change notification
● $onChanges
○ Called when “<” / input bindings are updated
○ parameter: a changes object including
■ keys for each changed property
■ previousValue and currentValue
● Very effective for
○ compute derived values
■ compute unread messages count
○ apply filtering or sorting to data
■ display various sets of messages according to a choice
http://blog.thoughtram.io/angularjs/2016/03/29/exploring-angular-1.5-lifecycle-hooks.html
41. Test a Component Controller
Pass inputs to the controller and test its behaviour
ngMock module has been updated with the
$componentController method
42. Test a Component
we can compile the element and test
● that it renders what we expected
● that it correctly reacts to user events
44. Components in Angular 2
Syntax, some costructs change, but
Component-based Architecture is even stronger
● no more stand-alone controllers
● even application home, first-level views become
components
○ component-based routing
● component metadata + Typescript allow for
○ better tooling support
○ completion, validation
○ more explicit API definition