SlideShare una empresa de Scribd logo
1 de 68
Tobias Bosch & Stefan Scheidt/ OPITZ CONSULTING GmbH JavaScript Data Binding mitjQuery Mobile
Wer sind wir? tobias.bosch@opitz-consulting.com (@tigbro) stefan.scheidt@opitz-consulting.com (@beezlebug)
Wer sind Sie?
In diesem Vortrag geht‘s um... ...die Entwicklung testbarer und wartbarer mobiler Web-Apps
Unser Beispiel
Mobile Web-Apps
Architektur
"Multi Page Web App" Browser Server HTML-Page Controller Backend Data Design: ,[object Object]
Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
Die  Standardfarben sind:UI Values
"AJAX Web App" Browser Server Controller Backend AJAX- Engine Change Data Design: ,[object Object]
Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
Die  Standardfarben sind:Events
"Single Page Web App" Browser Server Controller Backend Data Design: ,[object Object]
Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
Die  Standardfarben sind:,[object Object]
jQuery Mobile http://jquerymobile.com/
Noch einmal unser Beispiel...
<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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label>    </fieldset> </div> </div> jQuery Mobile Markup
DOM-Transformation durch jQuery Mobile
Vorher <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> <div class="ui-checkbox">   <input type="checkbox" name="todo.done" id="todo1">   <labelclass="ui-btnui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c">   <span class="ui-btn-innerui-btn-corner-all">   <span class="ui-btn-text">createa mobile todoapp</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"/> <labelfor="todo1">create a mobile todoapp</label> <div class="ui-checkbox">   <input type="checkbox" name="todo.done" id="todo1">   <labelclass="ui-btnui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c">   <span class="ui-btn-innerui-btn-corner-all">   <span class="ui-btn-text">createa mobile todoapp</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> Nachher jQuery Mobile Markup Transformation
Manuelles Binding
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
$('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create');     $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' +    '<labelfor="' + id + '">' + name + '</label>'; }
functionTodoController() { this.todos= []; this.inputText = ''; } TodoController.prototype = { addTodo: function() { this.todos.push({ name: this.inputText,  done: false  }); this.inputText= ''; } } Das Ziel ist aber:
Angular JS MVC with DependencyInjection Declarative UI Templates Two-Way Data Binding Framework http://angularjs.org/#/
Two-Way Databinding read write Controller read write DOM Data-binding watch watch
Scopes Scope $get(<expr>) Object $set(<expr>, <value>) $watch(<expr>, <callback>)
<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> <fieldsetdata-role="controlgroup">  <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label>    </fieldset> </div> </div> Das DOM
functionTodoController() { this.todos= []; this.inputText = ''; } TodoController.prototype = { addTodo: function() { this.todos.push({ name: this.inputText,  done: false  }); this.inputText= ''; } } Der Controller
inputText: 'newtodo' todos: [...] TodoController-Scope <div data-role="page" ng:controller="TodoController"> erzeugt <input type="text"  name="inputText" bindet bindet <div ng:repeat="todo in todos"> erzeugt Repeater Scope Repeater Scope Repeater Scope todo: { done: false name: 'makemoney' } todo: { done: false name: 'makemoney' } todo: { done: false name: 'makemoney' } <input type="checkbox" name="todo.done"/> bindet <label> {{todo.name}} </label> bindet
Damit ist das Ziel fast erreicht...
Die DOM-Manipulationen von jQuery Mobile und Angular JS müssen "nur noch" koordiniert werden.
Dazu später mehr!
MVC with DependencyInjection Angular JS Declarative UI Templates Two-Way Data Binding Framework http://angularjs.org/#/
var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) {    var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide();    }); } Backend-Anbindung
var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) {    var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide();    }); } Backend-Anbindung
var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) {    var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide();    }); } Backend-Anbindung
angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... }     return { read: read, write: write    } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... }     return { read: read, write: write    } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... }     return { read: read, write: write    } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... }     return { read: read, write: write    } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
functionTodoController(todoStore) {   ... } TodoController.$inject = ['todoStore']; Di für Controller
functionTodoController(todoStore) {   ... } TodoController.$inject = ['todoStore']; Di für Controller
functionTodoController(todoStore) {   ... } TodoController.$inject = ['todoStore']; Di für Controller
Onemorething... Integration von AngularJS und jQuery Mobile
jquery-mobile-angular-adapter Koordination von jQuery Mobile und Angular JS Erweiterungen für mobile Web-Apps Open Source unter  https://github.com/tigbro/ jquery-mobile-angular-adapter
Paging in Listen <div ng:repeat=            "todo in todos.$paged()"> ... </div> <div ng:if=      "todos.$paged().hasMorePages()"> <a href="#" ngm:click=     "todos.$paged().loadNextPage()">            Load more   </a> </div>
Paging in Listen <div ng:repeat=            "todo in todos.$paged()"> ... </div> <div ng:if=      "todos.$paged().hasMorePages()"> <a href="#" ngm:click=     "todos.$paged().loadNextPage()">            Load more   </a> </div>
Paging in Listen <div ng:repeat=            "todo in todos.$paged()"> ... </div> <div ng:if=      "todos.$paged().hasMorePages()"> <a href="#" ngm:click=     "todos.$paged().loadNextPage()">            Load more   </a> </div>
Mobile Events <div id="main" data-role="page"  ng:event="swipeleft:showSettings()">    ... </div> <div id="settings" data-role="page"  ng:event="swiperight:back()">    ... </div>
Navigation über Pages functionTodoController(todoStore, activePage) { ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos();         } }, showSettings: function() { this.activePage("#settings"); } };
Navigation über Pages functionTodoController(todoStore, activePage) { ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos();         } }, showSettings: function() { this.activePage("#settings"); } };
Navigation über Pages functionTodoController(todoStore, activePage){ ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos();         } }, showSettings: function() { this.activePage("#settings"); } };
Wait-Dialog Service waitDialog.show('loading'); waitDialog.hide(); waitDialog.show('clicktoabort',  onClickCallback);

Más contenido relacionado

Destacado

Procesoptimering Ved Medarbejderskabt Innovation
Procesoptimering Ved Medarbejderskabt InnovationProcesoptimering Ved Medarbejderskabt Innovation
Procesoptimering Ved Medarbejderskabt InnovationProplant.dk ApS
 
Investigación Acción-Participativa
Investigación  Acción-ParticipativaInvestigación  Acción-Participativa
Investigación Acción-Participativacarlyaldaz
 
Practical BIM Advice for Manufacturers
Practical BIM Advice for ManufacturersPractical BIM Advice for Manufacturers
Practical BIM Advice for ManufacturersThe NBS
 
computerarchiv-muenchen.de - Jahrekalender 2017 | C.Habermueller
computerarchiv-muenchen.de - Jahrekalender 2017  | C.Habermuellercomputerarchiv-muenchen.de - Jahrekalender 2017  | C.Habermueller
computerarchiv-muenchen.de - Jahrekalender 2017 | C.HabermuellerChristian Habermueller
 
Ken bain, lo que hacen los mejores profesores de universidad 1
Ken bain, lo que hacen los mejores profesores de universidad 1Ken bain, lo que hacen los mejores profesores de universidad 1
Ken bain, lo que hacen los mejores profesores de universidad 1aurelia garcia
 
Insight SaaS Overview - Cloud Computing
Insight SaaS Overview - Cloud ComputingInsight SaaS Overview - Cloud Computing
Insight SaaS Overview - Cloud Computingjgasior
 
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...Bauen digital Schweiz
 
лекц 4-инж.байгууламж
лекц 4-инж.байгууламжлекц 4-инж.байгууламж
лекц 4-инж.байгууламжradnaajav gerelchimeg
 

Destacado (12)

SMU Degree COLOR COPY
SMU Degree COLOR COPYSMU Degree COLOR COPY
SMU Degree COLOR COPY
 
.
..
.
 
Procesoptimering Ved Medarbejderskabt Innovation
Procesoptimering Ved Medarbejderskabt InnovationProcesoptimering Ved Medarbejderskabt Innovation
Procesoptimering Ved Medarbejderskabt Innovation
 
Investigación Acción-Participativa
Investigación  Acción-ParticipativaInvestigación  Acción-Participativa
Investigación Acción-Participativa
 
Practical BIM Advice for Manufacturers
Practical BIM Advice for ManufacturersPractical BIM Advice for Manufacturers
Practical BIM Advice for Manufacturers
 
computerarchiv-muenchen.de - Jahrekalender 2017 | C.Habermueller
computerarchiv-muenchen.de - Jahrekalender 2017  | C.Habermuellercomputerarchiv-muenchen.de - Jahrekalender 2017  | C.Habermueller
computerarchiv-muenchen.de - Jahrekalender 2017 | C.Habermueller
 
Nicknames
NicknamesNicknames
Nicknames
 
Ken bain, lo que hacen los mejores profesores de universidad 1
Ken bain, lo que hacen los mejores profesores de universidad 1Ken bain, lo que hacen los mejores profesores de universidad 1
Ken bain, lo que hacen los mejores profesores de universidad 1
 
Insight SaaS Overview - Cloud Computing
Insight SaaS Overview - Cloud ComputingInsight SaaS Overview - Cloud Computing
Insight SaaS Overview - Cloud Computing
 
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...
Schweizer BIM Kongress 2016: Referat von Steffen Lemmerzahl, SLIK Architekten...
 
лекц 4-инж.байгууламж
лекц 4-инж.байгууламжлекц 4-инж.байгууламж
лекц 4-инж.байгууламж
 
hsy_10_11[1].pdf
hsy_10_11[1].pdfhsy_10_11[1].pdf
hsy_10_11[1].pdf
 

Más de OPITZ CONSULTING Deutschland

Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"OPITZ CONSULTING Deutschland
 
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOPITZ CONSULTING Deutschland
 
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOPITZ CONSULTING Deutschland
 
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OPITZ CONSULTING Deutschland
 
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OPITZ CONSULTING Deutschland
 
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OPITZ CONSULTING Deutschland
 
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OPITZ CONSULTING Deutschland
 
OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OPITZ CONSULTING Deutschland
 
Effiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungEffiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungOPITZ CONSULTING Deutschland
 

Más de OPITZ CONSULTING Deutschland (20)

OC|Webcast: Grundlagen der Oracle Lizenzierung
OC|Webcast: Grundlagen der Oracle LizenzierungOC|Webcast: Grundlagen der Oracle Lizenzierung
OC|Webcast: Grundlagen der Oracle Lizenzierung
 
OC|Webcast "Java heute" vom 28.09.2021
OC|Webcast "Java heute" vom 28.09.2021OC|Webcast "Java heute" vom 28.09.2021
OC|Webcast "Java heute" vom 28.09.2021
 
OC|Webcast "Java heute" vom 24.08.2021
OC|Webcast "Java heute" vom 24.08.2021OC|Webcast "Java heute" vom 24.08.2021
OC|Webcast "Java heute" vom 24.08.2021
 
OC|Webcast "Daten wirklich nutzen"
OC|Webcast "Daten wirklich nutzen"OC|Webcast "Daten wirklich nutzen"
OC|Webcast "Daten wirklich nutzen"
 
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
Architecture Room Stuttgart - "Cloud-native ist nur ein Teil des Spiels!"
 
OC|Webcast "Willkommen in der Cloud!"
OC|Webcast "Willkommen in der Cloud!"OC|Webcast "Willkommen in der Cloud!"
OC|Webcast "Willkommen in der Cloud!"
 
OC|Webcast "Die neue Welt der Virtualisierung"
OC|Webcast "Die neue Welt der Virtualisierung"OC|Webcast "Die neue Welt der Virtualisierung"
OC|Webcast "Die neue Welt der Virtualisierung"
 
10 Thesen zur professionellen Softwareentwicklung
10 Thesen zur professionellen Softwareentwicklung10 Thesen zur professionellen Softwareentwicklung
10 Thesen zur professionellen Softwareentwicklung
 
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
OC|Webcast: Oracle Lizenzierung - Lizenznews 2021
 
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der PraxisOC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
OC|Webcast: Oracle Lizenzierung - Die größten Fallen in der Praxis
 
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und CloudOC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
OC|Webcast: Oracle Lizenzierung - Virtualisierung und Cloud
 
OC|Webcast: Grundlagen der Oracle-Lizenzierung
OC|Webcast: Grundlagen der Oracle-LizenzierungOC|Webcast: Grundlagen der Oracle-Lizenzierung
OC|Webcast: Grundlagen der Oracle-Lizenzierung
 
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
OC|Weekly Talk: Inspect’n’Adapt – Make Change come true!
 
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
OC|Webcast: Schnell und clever in die AWS Cloud – Migrationsszenarien und Han...
 
OC|Weekly Talk The Power of DevOps…
OC|Weekly Talk  The Power of DevOps…OC|Weekly Talk  The Power of DevOps…
OC|Weekly Talk The Power of DevOps…
 
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
OC|Weekly Talk: "Das müsste man mal digitalisieren" - Mit Low-Code schnell zu...
 
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
OC|Weekly Talk: Service Management – Was hat sich durch Corona geändert?
 
OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring OC|Weekly Talk - Digitales Coaching & Smart Sparring
OC|Weekly Talk - Digitales Coaching & Smart Sparring
 
OC|Weekly Talk - Beratung remote
OC|Weekly Talk - Beratung remoteOC|Weekly Talk - Beratung remote
OC|Weekly Talk - Beratung remote
 
Effiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud NutzungEffiziente Betriebsoptimierung durch Cloud Nutzung
Effiziente Betriebsoptimierung durch Cloud Nutzung
 

JavaScript Data Binding mit jQuery Mobile - OPITZ CONSULTING - Tobias Bosch - Stefan Scheidt

  • 1. Tobias Bosch & Stefan Scheidt/ OPITZ CONSULTING GmbH JavaScript Data Binding mitjQuery Mobile
  • 2. Wer sind wir? tobias.bosch@opitz-consulting.com (@tigbro) stefan.scheidt@opitz-consulting.com (@beezlebug)
  • 3.
  • 5. In diesem Vortrag geht‘s um... ...die Entwicklung testbarer und wartbarer mobiler Web-Apps
  • 9.
  • 10. Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
  • 11. Die Standardfarben sind:UI Values
  • 12.
  • 13. Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
  • 14. Die Standardfarben sind:Events
  • 15.
  • 16. Ebenso sind die Schriftarten als „OC 2009“ hinterlegt.
  • 17.
  • 19. Noch einmal unser Beispiel...
  • 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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 21. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 22. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 23. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 24. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 25. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 27. Vorher <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <labelclass="ui-btnui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-innerui-btn-corner-all"> <span class="ui-btn-text">createa mobile todoapp</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> jQuery Mobile Markup Transformation
  • 28. <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> <div class="ui-checkbox"> <input type="checkbox" name="todo.done" id="todo1"> <labelclass="ui-btnui-btn-up-c ui-btn-icon-left ui-btn-corner-all ui-checkbox-off" for="todo1" data-theme="c"> <span class="ui-btn-innerui-btn-corner-all"> <span class="ui-btn-text">createa mobile todoapp</span> <span class="ui-icon ui-icon-checkbox-off ui-icon-shadow"></span> </span> </label> </div> Nachher jQuery Mobile Markup Transformation
  • 30. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 31. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 32. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 33. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 34. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 35. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 36. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 37. $('#addTodo').submit(function(event) { addTodo(); event.preventDefault(); }); functionaddTodo() { varinputText = $('#inputText').val(); varlist = $('#todos'); varentryCount = list.find('input').length; list.append(entryTemplate(entryCount, inputText)); list.trigger('create'); $('#input').val(''); } functionentryTemplate(index, name) { varid = 'todo' + index; return '<input type="checkbox" id="' + id + '"/>' + '<labelfor="' + id + '">' + name + '</label>'; }
  • 38. functionTodoController() { this.todos= []; this.inputText = ''; } TodoController.prototype = { addTodo: function() { this.todos.push({ name: this.inputText, done: false }); this.inputText= ''; } } Das Ziel ist aber:
  • 39. Angular JS MVC with DependencyInjection Declarative UI Templates Two-Way Data Binding Framework http://angularjs.org/#/
  • 40. Two-Way Databinding read write Controller read write DOM Data-binding watch watch
  • 41. Scopes Scope $get(<expr>) Object $set(<expr>, <value>) $watch(<expr>, <callback>)
  • 42. <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> <fieldsetdata-role="controlgroup"> <input type="checkbox" id="todo1"/> <labelfor="todo1">create a mobile todoapp</label> </fieldset> </div> </div> Das DOM
  • 43. functionTodoController() { this.todos= []; this.inputText = ''; } TodoController.prototype = { addTodo: function() { this.todos.push({ name: this.inputText, done: false }); this.inputText= ''; } } Der Controller
  • 44. inputText: 'newtodo' todos: [...] TodoController-Scope <div data-role="page" ng:controller="TodoController"> erzeugt <input type="text" name="inputText" bindet bindet <div ng:repeat="todo in todos"> erzeugt Repeater Scope Repeater Scope Repeater Scope todo: { done: false name: 'makemoney' } todo: { done: false name: 'makemoney' } todo: { done: false name: 'makemoney' } <input type="checkbox" name="todo.done"/> bindet <label> {{todo.name}} </label> bindet
  • 45. Damit ist das Ziel fast erreicht...
  • 46. Die DOM-Manipulationen von jQuery Mobile und Angular JS müssen "nur noch" koordiniert werden.
  • 48. MVC with DependencyInjection Angular JS Declarative UI Templates Two-Way Data Binding Framework http://angularjs.org/#/
  • 49. var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); } Backend-Anbindung
  • 50. var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); } Backend-Anbindung
  • 51. var readUrl = 'https://secure.openkeyval.org/'; var jsonp = ...; var waitdialog = ...; functionread(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); } Backend-Anbindung
  • 52. angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... } return { read: read, write: write } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
  • 53. angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... } return { read: read, write: write } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
  • 54. angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... } return { read: read, write: write } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
  • 55. angular.service('jsonp', jsonpFactory); angular.service('waitdialog', waitdialogFactory); functiontodoStoreFactory(jsonp, waitdialog) { functionread(...) { ... } functionwrite(...) { ... } return { read: read, write: write } } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; angular.service('todostore', todoStoreFactory); Services und DI mit Angular
  • 56. functionTodoController(todoStore) { ... } TodoController.$inject = ['todoStore']; Di für Controller
  • 57. functionTodoController(todoStore) { ... } TodoController.$inject = ['todoStore']; Di für Controller
  • 58. functionTodoController(todoStore) { ... } TodoController.$inject = ['todoStore']; Di für Controller
  • 59. Onemorething... Integration von AngularJS und jQuery Mobile
  • 60. jquery-mobile-angular-adapter Koordination von jQuery Mobile und Angular JS Erweiterungen für mobile Web-Apps Open Source unter https://github.com/tigbro/ jquery-mobile-angular-adapter
  • 61. Paging in Listen <div ng:repeat= "todo in todos.$paged()"> ... </div> <div ng:if= "todos.$paged().hasMorePages()"> <a href="#" ngm:click= "todos.$paged().loadNextPage()"> Load more </a> </div>
  • 62. Paging in Listen <div ng:repeat= "todo in todos.$paged()"> ... </div> <div ng:if= "todos.$paged().hasMorePages()"> <a href="#" ngm:click= "todos.$paged().loadNextPage()"> Load more </a> </div>
  • 63. Paging in Listen <div ng:repeat= "todo in todos.$paged()"> ... </div> <div ng:if= "todos.$paged().hasMorePages()"> <a href="#" ngm:click= "todos.$paged().loadNextPage()"> Load more </a> </div>
  • 64. Mobile Events <div id="main" data-role="page" ng:event="swipeleft:showSettings()"> ... </div> <div id="settings" data-role="page" ng:event="swiperight:back()"> ... </div>
  • 65. Navigation über Pages functionTodoController(todoStore, activePage) { ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos(); } }, showSettings: function() { this.activePage("#settings"); } };
  • 66. Navigation über Pages functionTodoController(todoStore, activePage) { ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos(); } }, showSettings: function() { this.activePage("#settings"); } };
  • 67. Navigation über Pages functionTodoController(todoStore, activePage){ ... } TodoController.prototype= { onActivate: function(prevscope) { if (prevscope && prevscope.storageKey) { this.storageKey = prevscope.storageKey; this.refreshTodos(); } }, showSettings: function() { this.activePage("#settings"); } };
  • 68. Wait-Dialog Service waitDialog.show('loading'); waitDialog.hide(); waitDialog.show('clicktoabort', onClickCallback);
  • 69. Fazit Auch bei der Entwicklung von JavaScript Clients sollten geeignete Entwurfsmuster angewendet werden!
  • 70. Fazit Bibliotheken und Frameworks helfen bei der Umsetzung!
  • 71. Fazit Eine praxiserprobte Kombination: jQuery Mobile + AngularJS + Adapter
  • 72. In thehive 11: nectarandpollen byMax xx, http://www.flickr.com/photos/max_westby/4567762490 BooksBy Rodrigo Galindez, http://www.flickr.com/photos/rodrigogalindez/4637637337/
  • 73. Vielen Dankfür Ihr Interesse!@tigbro@beezlebug