Sie sind auf Seite 1von 13

Building up with

AngularJS
design patterns for dealing with UI
complexity.

Greg Weber yap.TV


You chose AngularJS.
Good job!
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?

A: Use plain-old JS object, don't need to


inherit from a special base: that gives us
greater flexibility.
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
Simplicy & Happiness Complexity & Sadness

// in controller // in service
$http('api').success (data) => var data = []
$scope.data = 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
(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', []); function ControllerZero($scope, sharedService) {


myModule.factory('mySharedService', function($rootScope) { $scope.handleClick = function(msg) {
var sharedService = {};
sharedService.data.message = msg;
// expose service data to angular scope };
$rootScope.sharedData = sharedService.data = {};
sharedService.data.message = '';
$scope.$watch('sharedData.message', function(msg) {
return sharedService;
$scope.message = msg;
});
});
}
function ControllerOne($scope, sharedService) {
$scope.$watch('sharedData.message', function() {
$scope.message = 'ONE: ' + sharedService.data.message;
});
}

http://jsfiddle.net/VxafF/
Using events
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) { http://jsfiddle.net/VxafF/
$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 AngularJS this can be
Events
changed to a function call

// in service
// in service
$rootScope.on 'change', changeData var data = []
$rootScope.broadcast('event', data) return {
changeData: => ...
// in controller
getData: => return data
$scope.on('event', ...)
}
// another controller
$rootScope.broadcast('change', []) // in controller, assign a function
$scope.data = service.getData
// in view: ng-bind="data()"
// could instead $watch the getter

// another controller
Communication via services: mutation
// in service // in controller
var data = []
var changeData = => $scope.data = service.data
$http(...).success (data) =>
data.length = 0
data.push(d) for d in data

return {
data: data
changeData: changeData
}
Dealing with complexity: not
AngularJS specific
* complex data modeling with adt.js
* managing complex UI State with statecharts
Data modeling with adt.js
https://github.com/natefaubion/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.

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
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)?

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.
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

Das könnte Ihnen auch gefallen