Design Patterns for JavaScript Web Apps Stefan Scheidt OPITZ CONSULTING GmbH
About me ... stefan.scheidt@opitz-consulting.com (@stefanscheidt)
Mission Markets The company's ambition is to help  Branchspreading organizations to be better than their  Over 600 customers competitors. 29% Trade / Logistics / Our services take place in partnership and 29% Supplier Industry / Services / are aimed at co-operation of many years. Telecommunications 42% Public Clients / Banks and Insurance Associations and Federations Portfolio Basic Data  Business IT Alignment  Founded in 1990  Business Information Management  400 employees  Business Process Management  8 offices  Application Development  SOA and System Integration  IT Infrastructure Management © OPITZ CONSULTING GmbH 2012 Seite 3
And … who are you?
This talk is about ... ... the development of testable and maintainable JavaScript Web Apps
This talk is about ... ... the development of testable and maintainable JavaScript Web Apps
Our Sample App ... http://tigbro.github.com/todo-mobile https://github.com/tigbro/todo-mobile
Software Design
"Multi Page Web App" Browser Server HTML-Page Controller Data Backend UI Values
"AJAX Web App" Browser Server Change AJAX- Controller Backend Data Engine Events
"Single Page Web App" Browser Server Controller Data Backend
UI Component Libraries
jQuery Mobile http://jquerymobile.com/
How can you create this?
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
DOM Transformations
<input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
<input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
Two Way Data Binding
Do it yourself "binding" ...
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
Wouldn't this be better ... ? function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; }
Angular JS Declarative MVC with UI Templates Dependency Injection Two-Way Framework Data Binding http://angularjs.org/#/
Two Way Databinding read read write Data- write DOM Controller binding watch watch
Scopes Scope Expressions $get(<expr>) 'inputText' 'todos.length' $set(<expr>, <value>) Object ... $watch(<expr>, <callback>)
Demo
<div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> The DOM
function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; } The Controller
<div data-role="page" TodoController Scope ng:controller="TodoController"> inputText: 'new todo' create <input type="text" todos: [...] name="inputText" bind bind <div ng:repeat="todo in todos"> create Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" name="todo.done"/> done: false done: false done: false bind name: 'makemoney' name: 'makemoney' name: 'makemoney' <label> {{todo.name}} } </label> bind }}
We are almost there, but ...
jQuery Mobile & AngularJS The problem: DOM transformations done by jQuery Mobile and AngularJS need to be coordinated!
jQuery Mobile & AngularJS Our Solution: jQuery Mobile Angular Adapter
jQuery Mobile Angular Adapter Integration of jQuery Mobile & AngularJS Extentions for mobile web development Open source on GitHub https://github.com/tigbro/jquery-mobile-angular-adapter
Dependency Injection
Dependency Injection is a design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
Dependency Injection is a design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
Sample: Calling the backend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
Sample: Calling the backend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created created by with "new" Factories
Sample: Calling the backend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory);
Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory() { function read(key, success) { ... } // ... return { read: read // ... } }
Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read, // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
Angular: DI for Services angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todoStore', todoStoreFactory);
Angular: DI for Controller // ... angular.service('todoStore', ...);
Angular: DI for Controller // ... angular.service('todoStore', ...); function TodoController(todoStore) { // do something with todoStore ... } TodoController.$inject = ['todoStore'];
Summary There are quite a lot of useful design patterns for the development of JavaScript Web Apps! Use them!
Summary Libraries and Frameworks can help you to get your stuff done!
In the hive 11: nectar and pollen by Max xx, http://www.flickr.com/photos/max_westby/4567762490 Books By Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/ IMG_1300-Edit by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/ Doble Via by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/ MacBook Pro Keyboard by superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/ Stubborn Last Drop by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/
The End ... @stefanscheidt @tigbro

Design Patterns for JavaScript Web Apps - JavaScript Conference 2012 - OPITZ CONSULTING - Stefan Scheidt

  • 1.
    Design Patterns for JavaScriptWeb Apps Stefan Scheidt OPITZ CONSULTING GmbH
  • 2.
  • 3.
    Mission Markets The company's ambition is to help  Branchspreading organizations to be better than their  Over 600 customers competitors. 29% Trade / Logistics / Our services take place in partnership and 29% Supplier Industry / Services / are aimed at co-operation of many years. Telecommunications 42% Public Clients / Banks and Insurance Associations and Federations Portfolio Basic Data  Business IT Alignment  Founded in 1990  Business Information Management  400 employees  Business Process Management  8 offices  Application Development  SOA and System Integration  IT Infrastructure Management © OPITZ CONSULTING GmbH 2012 Seite 3
  • 4.
    And … whoare you?
  • 5.
    This talk isabout ... ... the development of testable and maintainable JavaScript Web Apps
  • 6.
    This talk isabout ... ... the development of testable and maintainable JavaScript Web Apps
  • 7.
    Our Sample App... http://tigbro.github.com/todo-mobile https://github.com/tigbro/todo-mobile
  • 9.
  • 10.
    "Multi Page WebApp" Browser Server HTML-Page Controller Data Backend UI Values
  • 11.
    "AJAX Web App" Browser Server Change AJAX- Controller Backend Data Engine Events
  • 12.
    "Single Page WebApp" Browser Server Controller Data Backend
  • 13.
  • 14.
  • 15.
    How can youcreate this?
  • 16.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 17.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 18.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 19.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 20.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 21.
  • 22.
    <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
  • 23.
    <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todo app</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <label class="ui-btn ui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-inner ui-btn-corner-all"> <span class="ui-btn-text">create a mobile todo app</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
  • 24.
    Two Way DataBinding
  • 25.
    Do it yourself"binding" ...
  • 26.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 27.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 28.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 29.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 30.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 31.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 32.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 33.
    $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); function addTodo() { var inputText = $('#inputText').val(); var list = $('#todos'); var entryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#inputText').val(''); } function entryTemplate(index, name) { var id = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<label for="' + id + '">' + name + '</label>'; }
  • 34.
    Wouldn't this bebetter ... ? function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; }
  • 35.
    Angular JS Declarative MVC with UI Templates Dependency Injection Two-Way Framework Data Binding http://angularjs.org/#/
  • 36.
    Two Way Databinding read read write Data- write DOM Controller binding watch watch
  • 37.
    Scopes Scope Expressions $get(<expr>) 'inputText' 'todos.length' $set(<expr>, <value>) Object ... $watch(<expr>, <callback>)
  • 38.
  • 39.
    <div id="main" data-role="page"> <div data-role="header"> <h1>Todos</h1> <a href="">Save</a> <a href="#settings">Settings</a> </div> <div data-role="content"> <div data-role="fieldcontain"> <form data-ajax="false"> <input type="text"> </form> </div> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> The DOM
  • 40.
    function TodoController() { this.todos = []; this.inputText = ''; } TodoController.prototype.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; } The Controller
  • 41.
    <div data-role="page" TodoController Scope ng:controller="TodoController"> inputText: 'new todo' create <input type="text" todos: [...] name="inputText" bind bind <div ng:repeat="todo in todos"> create Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" name="todo.done"/> done: false done: false done: false bind name: 'makemoney' name: 'makemoney' name: 'makemoney' <label> {{todo.name}} } </label> bind }}
  • 42.
    We are almostthere, but ...
  • 43.
    jQuery Mobile &AngularJS The problem: DOM transformations done by jQuery Mobile and AngularJS need to be coordinated!
  • 44.
    jQuery Mobile &AngularJS Our Solution: jQuery Mobile Angular Adapter
  • 45.
    jQuery Mobile AngularAdapter Integration of jQuery Mobile & AngularJS Extentions for mobile web development Open source on GitHub https://github.com/tigbro/jquery-mobile-angular-adapter
  • 46.
  • 47.
    Dependency Injection isa design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  • 48.
    Dependency Injection isa design pattern whose purpose is to reduce the dependencies between components. It delegates the responsibility for creation and wiring of objects to an externaly configurable framework. http://de.wikipedia.org/wiki/Dependency_Injection
  • 49.
    Sample: Calling thebackend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
  • 50.
    Sample: Calling thebackend var readUrl = 'https://secure.openkeyval.org/'; TodoController.prototype.refreshTodos() { var self = this; read(readUrl, function(response) { self.todos = response; }); }
  • 51.
    Sample: Calling thebackend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 52.
    Sample: Calling thebackend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 53.
    Sample: Calling thebackend var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 54.
    Sample: Calling thebackend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created created by with "new" Factories
  • 55.
    Sample: Calling thebackend waitDialog todoController todoStore key value key value key value ... ... refreshToDos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
  • 56.
    Angular: DI forServices angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory);
  • 57.
    Angular: DI forServices angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory() { function read(key, success) { ... } // ... return { read: read // ... } }
  • 58.
    Angular: DI forServices angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read, // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
  • 59.
    Angular: DI forServices angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { ... } // ... return { read: read // ... } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todoStore', todoStoreFactory);
  • 60.
    Angular: DI forController // ... angular.service('todoStore', ...);
  • 61.
    Angular: DI forController // ... angular.service('todoStore', ...); function TodoController(todoStore) { // do something with todoStore ... } TodoController.$inject = ['todoStore'];
  • 62.
    Summary There are quitea lot of useful design patterns for the development of JavaScript Web Apps! Use them!
  • 63.
    Summary Libraries and Frameworks can help you to get your stuff done!
  • 64.
    In the hive11: nectar and pollen by Max xx, http://www.flickr.com/photos/max_westby/4567762490 Books By Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/ IMG_1300-Edit by Susan E Adams, http://www.flickr.com/photos/susanad813/3912914836/ Doble Via by amslerPIX, http://www.flickr.com/photos/amslerpix/6242266697/ MacBook Pro Keyboard by superstrikertwo, http://www.flickr.com/photos/superstrikertwo/4989727256/ Stubborn Last Drop by RogueSun Media, http://www.flickr.com/photos/shuttercat7/627798443/
  • 65.