SlideShare ist ein Scribd-Unternehmen logo
1 von 13
Downloaden Sie, um offline zu lesen
Building up with
AngularJS
design patterns for dealing with UI
complexity.
Greg Weber yap.TV
You chose AngularJS.
Good job!
A: Use plain-old JS object, don't need to
inherit from a special base: that gives us
greater flexibility.
Q: Why a good framework such as AngularJS?
A: 2-way data-binding eases your pain.
Q: Why AngularJS instead of other 2-way data-binding frameworks?
Note: I am not saying that AngularJS is superior to all other frameworks or that it is the best
choice for your team and your project.
Keeping Data up to date
* AngularJS keeps the *view* up to date based
on the data in the controller.
Problem: modularity demands different
controllers communicating via services.
* What happens when a view uses data that is
changed in another view?
Growing complexity
// in service
var data = []
changeData = =>
$http('api').success (data) =>
data = []
return { data: data }
// in first controller
$scope.data = service.data
// in second controller
service.changeData()
Complexity Fail: the controller is referencing the
original data, doesn't know about new value
// in controller
$http('api').success (data) =>
$scope.data = data​
Simplicy & Happiness Complexity & Sadness
(Overly) simple approach: placing data on the $rootScope and watching it on
different controllers.
Problems: This could lead to a collision, and also in the case of an isolated
scope will not be propagated.
var myModule = angular.module('myModule', []);
myModule.factory('mySharedService', function($rootScope) {
var sharedService = {};
// expose service data to angular scope
$rootScope.sharedData = sharedService.data = {};
sharedService.data.message = '';
return sharedService;
});
http://jsfiddle.net/VxafF/
function ControllerZero($scope, sharedService) {
$scope.handleClick = function(msg) {
sharedService.data.message = msg;
};
$scope.$watch('sharedData.message', function(msg) {
$scope.message = msg;
});
}
function ControllerOne($scope, sharedService) {
$scope.$watch('sharedData.message', function() {
$scope.message = 'ONE: ' + sharedService.data.message;
});
}
Using events
http://jsfiddle.net/VxafF/
Using events we can clearly communicate between controllers. And when we are
communicating with code not integrated with angular, this is often the best approach
Problem:
● using fragile strings. Potential (unexplored) solution: use signals.js or use variables
that contain the string names
● Usage is a bit more obscure: we will likely end up broadcasting events to every
controller whether they care about them or not. We will search for a string to find the
event source rather than looking for a service
● Some boilerplate in the controller
myModule.run(function($rootScope) {
$rootScope.$on('handleEmit', function(event, args) {
$rootScope.$broadcast('handleBroadcast', args);
});
});
function ControllerZero($scope) {
$scope.handleClick = function(msg) {
$scope.$emit('handleEmit', {message: msg});
};
}
function ControllerOne($scope) {
$scope.$on('handleBroadcast', function(event, args) {
$scope.message = 'ONE: ' + args.message;
});
}
Communication via services: getters
// in service
$rootScope.on 'change', changeData
$rootScope.broadcast('event', data)
// in controller
$scope.on('event', ...)
// another controller
$rootScope.broadcast('change', [])
In AngularJS this can be
changed to a function call
// in service
var data = []
return {
changeData: => ...
getData: => return data
}
// in controller, assign a function
$scope.data = service.getData
// in view: ng-bind="data()"
// could instead $watch the getter
// another controller
service.changeData([])
Events
Communication via services: mutation
// in service
var data = []
var changeData = =>
$http(...).success (data) =>
data.length = 0
data.push(d) for d in data
return {
data: data
changeData: changeData
}
​
// in controller
$scope.data = service.data
Dealing with complexity: not
AngularJS specific
* complex data modeling with adt.js
* managing complex UI State with statecharts
Data modeling with adt.js
Facebook feed =>
Each Facebook feed item can be an
entirely different kind of data:
● picture
● video
● link share
● status update
● surveys
Original code: mostly undefined/null
object fields (single table inheritance),
type is differentiated by a 'kind' field.
https://github.com/natefaubion/adt.js
New code: a DRY schema that does some data
conversion/validation, and it is clear what fields are actually supposed
to exist. Our code is our documentation.
A schema is just a key-pair of field name and a function that can
coerce the data (parseInt) or throw an exception.
Statecharts: dealing with complexity
Solution: be very *explicit* about using state.
Statecharts were created to manage the complexity of Jet Fighter software. The existing giant
specification still did not explain how everything interacted. Using statecharts they were able to
document the interaction and communicate it to non-engineers.
Problem: Our UI has implicit state mutation:
we switch from one view (state) to another. What transitions are valid? What should happen as state
changes? How do we handle concurrent states (different views at once, popups, etc)?
Statechart: alternatives
* Just use routing. Problems: concurrent states,
doing proper nested state transitions,
remembering history of different branches.
* Just use a FSM (multiple FSMs for concurrent
states). Problem: Nested states
* Stativus library: full-featured, large code base,
some bugs
* A few other non-maintained/GPL libraries
* Wrote my own StateChart implemenation
instead. It is smaller & levarages TypeScript.
Will open source soon.
Statecharts: code
state.goTo()
exit existing states & enter new state,
calling all exit and enter callbacks
exiting creates a history state that we
can go back (like a back button)
exiting: authenticate history of root
entering loggedin
logged in & starting
entering display
entering guide
entering guide-Tuesday
exiting: guide-Tuesday history of guide
exiting: guide history of display
entering shows
entering favorites
entering myNew
exiting: myNew history of favorites
exiting: favorites history of shows
entering show-search
exiting: show-search history of shows
exiting: shows history of display
entering guide
entering guide-Tuesday

Weitere ähnliche Inhalte

Was ist angesagt?

Angular custom directives
Angular custom directivesAngular custom directives
Angular custom directives
Alexe Bogdan
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
Evan Schultz
 

Was ist angesagt? (20)

Redux workshop
Redux workshopRedux workshop
Redux workshop
 
redux and angular - up and running
redux and angular - up and runningredux and angular - up and running
redux and angular - up and running
 
Vuex: X factor for Vue
Vuex: X factor for VueVuex: X factor for Vue
Vuex: X factor for Vue
 
React
ReactReact
React
 
What 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architecturesWhat 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architectures
 
React + Redux + TypeScript === ♥
React + Redux + TypeScript === ♥React + Redux + TypeScript === ♥
React + Redux + TypeScript === ♥
 
Angular 2 KTS
Angular 2 KTSAngular 2 KTS
Angular 2 KTS
 
AngularJS Basic Training
AngularJS Basic TrainingAngularJS Basic Training
AngularJS Basic Training
 
Backbone.js
Backbone.jsBackbone.js
Backbone.js
 
SUGCon 2014 Sitecore MVC
SUGCon 2014 Sitecore MVCSUGCon 2014 Sitecore MVC
SUGCon 2014 Sitecore MVC
 
React: High level overview for backend developers
React: High level overview for backend developersReact: High level overview for backend developers
React: High level overview for backend developers
 
Reduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android BetterReduxing UI: Borrowing the Best of Web to Make Android Better
Reduxing UI: Borrowing the Best of Web to Make Android Better
 
Angular custom directives
Angular custom directivesAngular custom directives
Angular custom directives
 
The Road To Redux
The Road To ReduxThe Road To Redux
The Road To Redux
 
Client Side MVC & Angular
Client Side MVC & AngularClient Side MVC & Angular
Client Side MVC & Angular
 
React and MobX: A Truly Reactive App
React and MobX:  A Truly Reactive AppReact and MobX:  A Truly Reactive App
React and MobX: A Truly Reactive App
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
 
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js  Better Together: Building Scalable Real Time Collaborative Apps with Node.js
Better Together: Building Scalable Real Time Collaborative Apps with Node.js
 
AngularJs
AngularJsAngularJs
AngularJs
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
 

Ähnlich wie Angular js meetup

Memento Pattern Implementation
Memento Pattern ImplementationMemento Pattern Implementation
Memento Pattern Implementation
Steve Widom
 
Intro to React - Featuring Modern JavaScript
Intro to React - Featuring Modern JavaScriptIntro to React - Featuring Modern JavaScript
Intro to React - Featuring Modern JavaScript
jasonsich
 

Ähnlich wie Angular js meetup (20)

Memento Pattern Implementation
Memento Pattern ImplementationMemento Pattern Implementation
Memento Pattern Implementation
 
Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016Microservices with .Net - NDC Sydney, 2016
Microservices with .Net - NDC Sydney, 2016
 
DZone_RC_RxJS
DZone_RC_RxJSDZone_RC_RxJS
DZone_RC_RxJS
 
Angular js 2.0 beta
Angular js 2.0 betaAngular js 2.0 beta
Angular js 2.0 beta
 
Dev381.Pp
Dev381.PpDev381.Pp
Dev381.Pp
 
Lift Framework
Lift FrameworkLift Framework
Lift Framework
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
Angular js 2.0
Angular js 2.0Angular js 2.0
Angular js 2.0
 
Feedback using Angularjs + Typescript at Serenytics
Feedback using Angularjs +  Typescript at SerenyticsFeedback using Angularjs +  Typescript at Serenytics
Feedback using Angularjs + Typescript at Serenytics
 
AngularJS Beginner Day One
AngularJS Beginner Day OneAngularJS Beginner Day One
AngularJS Beginner Day One
 
Understanding react hooks
Understanding react hooksUnderstanding react hooks
Understanding react hooks
 
Advanced web application architecture Way2Web
Advanced web application architecture Way2WebAdvanced web application architecture Way2Web
Advanced web application architecture Way2Web
 
Intro to React - Featuring Modern JavaScript
Intro to React - Featuring Modern JavaScriptIntro to React - Featuring Modern JavaScript
Intro to React - Featuring Modern JavaScript
 
Server side programming bt0083
Server side programming bt0083Server side programming bt0083
Server side programming bt0083
 
iOS Architectures
iOS ArchitecturesiOS Architectures
iOS Architectures
 
Multi-tenancy with Rails
Multi-tenancy with RailsMulti-tenancy with Rails
Multi-tenancy with Rails
 
A sane approach to microservices
A sane approach to microservicesA sane approach to microservices
A sane approach to microservices
 
Programming Without Coding Technology (PWCT) Features - Programming Paradigm
Programming Without Coding Technology (PWCT) Features - Programming ParadigmProgramming Without Coding Technology (PWCT) Features - Programming Paradigm
Programming Without Coding Technology (PWCT) Features - Programming Paradigm
 
Angular js
Angular jsAngular js
Angular js
 
Node.js for enterprise - JS Conference
Node.js for enterprise - JS ConferenceNode.js for enterprise - JS Conference
Node.js for enterprise - JS Conference
 

Angular js meetup

  • 1. Building up with AngularJS design patterns for dealing with UI complexity. Greg Weber yap.TV
  • 2. You chose AngularJS. Good job! A: Use plain-old JS object, don't need to inherit from a special base: that gives us greater flexibility. Q: Why a good framework such as AngularJS? A: 2-way data-binding eases your pain. Q: Why AngularJS instead of other 2-way data-binding frameworks? Note: I am not saying that AngularJS is superior to all other frameworks or that it is the best choice for your team and your project.
  • 3. Keeping Data up to date * AngularJS keeps the *view* up to date based on the data in the controller. Problem: modularity demands different controllers communicating via services. * What happens when a view uses data that is changed in another view?
  • 4. Growing complexity // in service var data = [] changeData = => $http('api').success (data) => data = [] return { data: data } // in first controller $scope.data = service.data // in second controller service.changeData() Complexity Fail: the controller is referencing the original data, doesn't know about new value // in controller $http('api').success (data) => $scope.data = data​ Simplicy & Happiness Complexity & Sadness
  • 5. (Overly) simple approach: placing data on the $rootScope and watching it on different controllers. Problems: This could lead to a collision, and also in the case of an isolated scope will not be propagated. var myModule = angular.module('myModule', []); myModule.factory('mySharedService', function($rootScope) { var sharedService = {}; // expose service data to angular scope $rootScope.sharedData = sharedService.data = {}; sharedService.data.message = ''; return sharedService; }); http://jsfiddle.net/VxafF/ function ControllerZero($scope, sharedService) { $scope.handleClick = function(msg) { sharedService.data.message = msg; }; $scope.$watch('sharedData.message', function(msg) { $scope.message = msg; }); } function ControllerOne($scope, sharedService) { $scope.$watch('sharedData.message', function() { $scope.message = 'ONE: ' + sharedService.data.message; }); }
  • 6. Using events http://jsfiddle.net/VxafF/ Using events we can clearly communicate between controllers. And when we are communicating with code not integrated with angular, this is often the best approach Problem: ● using fragile strings. Potential (unexplored) solution: use signals.js or use variables that contain the string names ● Usage is a bit more obscure: we will likely end up broadcasting events to every controller whether they care about them or not. We will search for a string to find the event source rather than looking for a service ● Some boilerplate in the controller myModule.run(function($rootScope) { $rootScope.$on('handleEmit', function(event, args) { $rootScope.$broadcast('handleBroadcast', args); }); }); function ControllerZero($scope) { $scope.handleClick = function(msg) { $scope.$emit('handleEmit', {message: msg}); }; } function ControllerOne($scope) { $scope.$on('handleBroadcast', function(event, args) { $scope.message = 'ONE: ' + args.message; }); }
  • 7. Communication via services: getters // in service $rootScope.on 'change', changeData $rootScope.broadcast('event', data) // in controller $scope.on('event', ...) // another controller $rootScope.broadcast('change', []) In AngularJS this can be changed to a function call // in service var data = [] return { changeData: => ... getData: => return data } // in controller, assign a function $scope.data = service.getData // in view: ng-bind="data()" // could instead $watch the getter // another controller service.changeData([]) Events
  • 8. Communication via services: mutation // in service var data = [] var changeData = => $http(...).success (data) => data.length = 0 data.push(d) for d in data return { data: data changeData: changeData } ​ // in controller $scope.data = service.data
  • 9. Dealing with complexity: not AngularJS specific * complex data modeling with adt.js * managing complex UI State with statecharts
  • 10. Data modeling with adt.js Facebook feed => Each Facebook feed item can be an entirely different kind of data: ● picture ● video ● link share ● status update ● surveys Original code: mostly undefined/null object fields (single table inheritance), type is differentiated by a 'kind' field. https://github.com/natefaubion/adt.js New code: a DRY schema that does some data conversion/validation, and it is clear what fields are actually supposed to exist. Our code is our documentation. A schema is just a key-pair of field name and a function that can coerce the data (parseInt) or throw an exception.
  • 11. Statecharts: dealing with complexity Solution: be very *explicit* about using state. Statecharts were created to manage the complexity of Jet Fighter software. The existing giant specification still did not explain how everything interacted. Using statecharts they were able to document the interaction and communicate it to non-engineers. Problem: Our UI has implicit state mutation: we switch from one view (state) to another. What transitions are valid? What should happen as state changes? How do we handle concurrent states (different views at once, popups, etc)?
  • 12. Statechart: alternatives * Just use routing. Problems: concurrent states, doing proper nested state transitions, remembering history of different branches. * Just use a FSM (multiple FSMs for concurrent states). Problem: Nested states * Stativus library: full-featured, large code base, some bugs * A few other non-maintained/GPL libraries * Wrote my own StateChart implemenation instead. It is smaller & levarages TypeScript. Will open source soon.
  • 13. Statecharts: code state.goTo() exit existing states & enter new state, calling all exit and enter callbacks exiting creates a history state that we can go back (like a back button) exiting: authenticate history of root entering loggedin logged in & starting entering display entering guide entering guide-Tuesday exiting: guide-Tuesday history of guide exiting: guide history of display entering shows entering favorites entering myNew exiting: myNew history of favorites exiting: favorites history of shows entering show-search exiting: show-search history of shows exiting: shows history of display entering guide entering guide-Tuesday