Weitere ähnliche Inhalte Mehr von OPITZ CONSULTING Deutschland (20) 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) 5. In diesem Vortrag geht‘s um... ...die Entwicklung testbarer und wartbarer mobiler Web-Apps 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/#/ 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 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 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"); } }; 69. Fazit Auch bei der Entwicklung von JavaScript Clients sollten geeignete Entwurfsmuster angewendet werden! 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/