SlideShare ist ein Scribd-Unternehmen logo
1 von 89
Entwurfsmuster für
mobile JavaScript-Web-Apps

Tobias Bosch
OPITZ CONSULTING Deutschland GmbH
Wer bin ich?



tobias.bosch@opitz-consulting.com
            (@tigbro)
Mission                                          Märkte
Wir entwickeln gemeinsam mit allen                Branchenübergreifend
Branchen Lösungen, die dazu führen, dass          Über 600 Kunden
sich diese Organisationen besser entwickeln                                           29%
als ihr Wettbewerb.                                                29%
                                                                                      Handel / Logistik /
                                                                                      Dienstleistungen
                                                 Industrie / Versorger /
Unsere Dienstleistung erfolgt                      Telekommunikation
partnerschaftlich und ist auf eine langjährige                                 42%
Zusammenarbeit angelegt.                                                       Öffentliche Auftraggeber / Banken und
                                                                               Versicherungen / Vereine und Verbände



Leistungsangebot                                 Eckdaten
 Business IT Alignment                           Gründung 1990
 Business Information Management                 400 Mitarbeiter
 Business Process Management                     8 Standorte
 Anwendungsentwicklung
 SOA und System-Integration
 IT-Infrastruktur-Management


                                                                           © OPITZ CONSULTING GmbH 2012         Seite 3
Wer sind Sie?
In diesem Vortrag geht‘s um ...

     ... die Entwicklung
 testbarer und wartbarer
mobiler JavaScript Web-Apps
In diesem Vortrag geht‘s um ...

     ... die Entwicklung
 testbarer und wartbarer
mobiler JavaScript Web-Apps
In diesem Vortrag geht‘s um ...

     ... die Entwicklung
 testbarer und wartbarer
mobiler JavaScript Web-Apps
Die Beispiel-App ...

http://tigbro.github.com/todo-mobile
https://github.com/tigbro/todo-mobile
Architektur
"Multi Page Web App"

Browser                             Server


           HTML-Page
                        Model
                         View       Data     Backend
           UI Values   Controller
"AJAX Web App"

Browser                         Server


          Change    Model
AJAX-                View                Ba
                                Data
Engine             Controller
          Events
"Single Page Web App"

  Browser             Server


   Model
    View       Data   Backend
  Controller
Komponenten-Bibliotheken
jQuery Mobile




 http://jquerymobile.com/
Die Beispiel-App
<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-Transformation
durch jQuery-Mobile
<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
Manuelles 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>';
}
Das Ziel sollte aber sein:

   function TodoController() {
       this.todos = [];
       this.inputText = '';
       this.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>)
                                            ...



$watch(<expr>, <callback>)
Demo
Das Ziel ...
function TodoController() {
    this.todos = [];
    this.inputText = '';
    this.addTodo = function() {
        this.todos.push({
            name: this.inputText,
            done: false
        });
        this.inputText = '';
    };
}
Mit Angular ...
function TodoController($scope) {
    $scope.todos = [];
    $scope.inputText = '';
    $scope.addTodo = function() {
        $scope.todos.push({
            name: $scope.inputText,
            done: false
        });
        $scope.inputText = '';
    };
}
TodoController.$inject = ['$scope'];
<div data-role="page"                      TodoController-Scope
     ng-controller="TodoController">
                                           inputText: 'new todo'
                          erzeugt
  <input type="text"                       todos: [...]
                                 bindet
         ng-model="inputText"
                                    bindet
  <div ng-repeat="todo in todos">

                    erzeugt                           Repeater Scope
                                                     Repeater Scope
                                                    Repeater Scope
                                            todo: {
                                             todo:
                                           todo: { {
      <input type="checkbox"
             ng-model="todo.done"/>                   done: false
                                                     done: false
                                                    done: false
                                  bindet
                                                      name: 'makemoney'
                                                     name: 'makemoney'
                                                    name: 'makemoney'
      <label>
        {{todo.name}}                           }
      </label>
                                bindet     }}
jQuery Mobile und AngularJS

        Das Problem:

   Die DOM-Manipulationen von
   jQuery Mobile und AngularJS
   müssen koordiniert werden!
jQuery Mobile und AngularJS

         Die Lösung:


jQuery Mobile Angular Adapter
jQuery Mobile Angular Adapter

Koordination von jQuery Mobile und AngularJS

    Erweiterungen für mobile Web-Apps

             Open Source unter
         https://github.com/tigbro/
       jquery-mobile-angular-adapter
Dependency Injection
Dependency Injection ist ein Entwurfsmuster
 und dient dazu, die Abhängigkeiten zwischen
        Komponenten zu minimieren.


    Es überträgt die Verantwortung für das
Erzeugen und die Verknüpfung von Objekten an
    ein extern konfigurierbares Framework


                   http://de.wikipedia.org/wiki/Dependency_Injection
Dependency Injection ist ein Entwurfsmuster
 und dient dazu, die Abhängigkeiten zwischen
        Komponenten zu minimieren.


    Es überträgt die Verantwortung für das
Erzeugen und die Verknüpfung von Objekten an
    ein extern konfigurierbares Framework


                   http://de.wikipedia.org/wiki/Dependency_Injection
Beispiel: Backend-Anbindung

 function refreshTodos() {
     var self = this;
     read('ToDoApp', function(response) {
         self.todos = response;
     });
 }
Beispiel: Backend-Anbindung

 function refreshTodos() {
     var self = this;
     read('ToDoApp', function(response) {
         self.todos = response;
     });
 }
Beispiel: Backend-Anbindung

 var readUrl = 'https://secure.openkeyval.org/';

 function read(key, success) {
     var url = readUrl + key;
     waitdialog.show();
     jsonp(url, function(data) {
         success(data);
         waitdialog.hide();
     });
 }
Beispiel: Backend-Anbindung

 var readUrl = 'https://secure.openkeyval.org/';

 function read(key, success) {
     var url = readUrl + key;
     waitdialog.show();
     jsonp(url, function(data) {
         success(data);
         waitdialog.hide();
     });
 }
Beispiel: Backend-Anbindung

 var readUrl = 'https://secure.openkeyval.org/';

 function read(key, success) {
     var url = readUrl + key;
     waitdialog.show();
     jsonp(url, function(data) {
         success(data);
         waitdialog.hide();
     });
 }
Beispiel: Backend-Anbindung

                                                   waitDialog
todoController           todoStore                 key     value
key              value   key          value        ...     ...
refreshTodos ...         read         ...
todoStore                waitDialog
                         jsonp                     jsonp
                                                   key     value
                                                   ...     ...

                                      created by
                                       Factories
Beispiel: Backend-Anbindung

                                                  waitDialog
todoController               todoStore            key     value
key              value       key          value   ...     ...
refreshTodos ...             read         ...
todoStore                    waitDialog
                             jsonp                jsonp
                                                  key     value
                                                  ...     ...
                             created by
                         Dependency Injection
Angular JS

Declarative                       MVC with
UI Templates                      Dependency Injection




Two-Way                           Framework
Data Binding




        http://angularjs.org/#/
Services und DI mit Angular
function jsonpFactory() {
  // returns jsonp function
  // ...
}
function waitdialogFactory() {
  // returns waitdialog object
  // ...
}
Services und DI mit Angular
var module = angular.module("todo", []);
Services und DI mit Angular
var module = angular.module("todo", []);
module.factory('jsonp', jsonpFactory);
module.factory('waitdialog', waitdialogFactory);
Services und DI mit Angular
var module = angular.module("todo", []);
module.factory('jsonp', jsonpFactory);
module.factory('waitdialog', waitdialogFactory);

function todoStoreFactory(jsonp, waitdialog) {
    function read(key, success) {
        // use jsonp, waitdialog here
    }
    return {
        read: read
    };
}
Services und DI mit Angular
var module = angular.module("todo", []);
module.factory('jsonp', jsonpFactory);
module.factory('waitdialog', waitdialogFactory);

function todoStoreFactory(jsonp, waitdialog) {
    function read(key, success) {
        // use jsonp, waitdialog here
    }
    return {
        read: read
    };
}
todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
Services und DI mit Angular
var module = angular.module("todo", []);
module.factory('jsonp', jsonpFactory);
module.factory('waitdialog', waitdialogFactory);

function todoStoreFactory(jsonp, waitdialog) {
    // ...
}
todoStoreFactory.$inject = ['jsonp', 'waitdialog'];

module.factory('todoStore', todoStoreFactory);
Controller und DI mit Angular

function TodoController($scope, todoStore) {
  ...
}
TodoController.$inject = ['$scope', 'todoStore'];

module.controller("rylc.TodoController", TodoController);
Controller und DI mit Angular

function TodoController($scope, todoStore) {
  ...
}
TodoController.$inject = ['$scope', 'todoStore'];

module.controller("rylc.TodoController", TodoController);
Controller und DI mit Angular

function TodoController($scope, todoStore) {
  ...
}
TodoController.$inject = ['$scope', 'todoStore'];

module.controller("rylc.TodoController", TodoController);
jQuery Mobile Angular Adapter

Koordination von jQuery Mobile und AngularJS

    Erweiterungen für mobile Web-Apps

             Open Source unter
         https://github.com/tigbro/
       jquery-mobile-angular-adapter
jQuery Mobile Angular Adapter



       Mobile Events
<div id="welcomePage" data-role="page"
     ngm-pagebeforeshow="rental.prefetchMasterData()"
     ngm-pagebeforehide="rental.clearMessages()">
    ...
</div>
<div id="welcomePage" data-role="page"
     ngm-pagebeforeshow="rental.prefetchMasterData()"
     ngm-pagebeforehide="rental.clearMessages()">
    ...
</div>


                      Unterstütze Events:

              vclick                swipe
              pagebeforeshow        swiperight
              pageshow              swipeleft
              pagebeforehide        tap
              pagehide              taphold
jQuery Mobile Angular Adapter



      Shared Controller
LoginPage
<div id="loginPage"                        Scope
     ng-controller="LoginController">
                                        login

  <a ngm-click="login()">
LoginPage
<div id="loginPage"                        Scope
     ng-controller="LoginController">
                                        login

  <a ngm-click="login()">

<div id="welcomePage"                   WelcomePage
     ng-controller="WelcomeController">    Scope

                                        logout

  <a ngm-click="logout()">
LoginPage
<div id="loginPage"                        Scope
     ngm-shared-controller=
                                                      Authentication-
     "auth:AuthenticationController">   auth          Controller Scope
  <a ngm-click="login()">
                                                      login
                                                      logout
<div id="welcomePage"                   WelcomePage
     ngm-shared-controller=                Scope
     "auth:AuthenticationController">
                                        auth
  <a ngm-click="logout()">
LoginPage
<div id="loginPage"                        Scope
     ngm-shared-controller=
                                                      Authentication-
     "auth:AuthenticationController">   auth          Controller Scope
  <a ngm-click="auth.login()">
                                                      login
                                                      logout
<div id="welcomePage"                   WelcomePage
     ngm-shared-controller=                Scope
     "auth:AuthenticationController">
                                        auth
  <a ngm-click="auth.logout()">
LoginPage
<div id="loginPage"                        Scope
     ngm-shared-controller=
                                                      Authentication-
     "auth:AuthenticationController">   auth          Controller Scope
  <a ngm-click="auth.login()">
                                                      login
                                                      logout
<div id="welcomePage"                   WelcomePage
     ngm-shared-controller=                Scope
     "auth:AuthenticationController,
     "rental:RentalController">
                                        auth
  <a ngm-click="auth.logout()">         rental
  <a ngm-click="rental.initRental()">
                                                          Rental-
                                                      Controller Scope

                                                      initRental
                                                      searchCar
LoginPage
<div id="loginPage"                        Scope
     ngm-shared-controller=
                                                      Authentication-
     "auth:AuthenticationController">   auth          Controller Scope
  <a ngm-click="auth.login()">
                                                      login
                                                      logout
<div id="welcomePage"                   WelcomePage
     ngm-shared-controller=                Scope
     "auth:AuthenticationController,
     "rental:RentalController">
                                        auth
  <a ngm-click="auth.logout()">         rental
  <a ngm-click="rental.initRental()">
                                                          Rental-
<div id="rentalPage"                                  Controller Scope
     ngm-shared-controller=              RentalPage
     "auth:AuthenticationController,       Scope      initRental
     "rental:RentalController">                       searchCar

                                        auth
  <a ngm-click="rental.searchCars()">   rental
jQuery Mobile Angular Adapter



         Wait Dialog
waitDialog.show('loading');

waitDialog.hide();




waitDialog.show('click to abort',
       onClickCallback);
jQuery Mobile Angular Adapter



     Paging / Load More
<fieldset ng-repeat="todo in todos | paged:'pager':5">
      <input type="checkbox" ng-model="todo.done" id="checked">
      <label for="checked">{{todo.name}}</label>
</fieldset>

<div ngm-if="pager.hasMore">
    <a href="#" ngm-click="pager.loadMore()" data-role="button">
            Load more
    </a>
</div>
<fieldset ng-repeat="todo in todos | paged:'pager':5">
      <input type="checkbox" ng-model="todo.done" id="checked">
      <label for="checked">{{todo.name}}</label>
</fieldset>

<div ngm-if="pager.hasMore">
    <a href="#" ngm-click="pager.loadMore()" data-role="button">
            Load more
    </a>
</div>
Fazit


     Auch bei der Entwicklung
      von JavaScript Clients
sollten geeignete Entwurfsmuster
       angewendet werden!
Fazit



Bibliotheken und Frameworks
  helfen bei der Umsetzung!
Fazit

Eine praxiserprobte Kombination für die
    Entwicklung mobiler Web-Apps:

            jQuery Mobile
              + AngularJS
               + Adapter
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/
Vielen Dank
für Ihr Interesse!
     @tigbro
www.opitz-consulting.com/go_mobile

Weitere ähnliche Inhalte

Was ist angesagt?

New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2raj lex
 
City bars workshop
City bars workshopCity bars workshop
City bars workshopJames Pearce
 
2015 Key Ingredient Cook-Off
2015 Key Ingredient Cook-Off2015 Key Ingredient Cook-Off
2015 Key Ingredient Cook-Offirwinvifxcfesre
 
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...irwinvifxcfesre
 
Web Components und Polymer: Klassen für das Web
Web Components und Polymer: Klassen für das WebWeb Components und Polymer: Klassen für das Web
Web Components und Polymer: Klassen für das Webinovex GmbH
 
Intro to jQuery UI
Intro to jQuery UIIntro to jQuery UI
Intro to jQuery UIappendTo
 

Was ist angesagt? (6)

New text document (2) 2
New text document (2) 2New text document (2) 2
New text document (2) 2
 
City bars workshop
City bars workshopCity bars workshop
City bars workshop
 
2015 Key Ingredient Cook-Off
2015 Key Ingredient Cook-Off2015 Key Ingredient Cook-Off
2015 Key Ingredient Cook-Off
 
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
Peek inside the fantastical Ukrainian Village home and studio of artists Jare...
 
Web Components und Polymer: Klassen für das Web
Web Components und Polymer: Klassen für das WebWeb Components und Polymer: Klassen für das Web
Web Components und Polymer: Klassen für das Web
 
Intro to jQuery UI
Intro to jQuery UIIntro to jQuery UI
Intro to jQuery UI
 

Mehr von 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
 

Mehr von 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
 

Entwurfsmuster für mobile JavaScript-Web-Apps - WebTechConference 2012

  • 1. Entwurfsmuster für mobile JavaScript-Web-Apps Tobias Bosch OPITZ CONSULTING Deutschland GmbH
  • 3. Mission Märkte Wir entwickeln gemeinsam mit allen  Branchenübergreifend Branchen Lösungen, die dazu führen, dass  Über 600 Kunden sich diese Organisationen besser entwickeln 29% als ihr Wettbewerb. 29% Handel / Logistik / Dienstleistungen Industrie / Versorger / Unsere Dienstleistung erfolgt Telekommunikation partnerschaftlich und ist auf eine langjährige 42% Zusammenarbeit angelegt. Öffentliche Auftraggeber / Banken und Versicherungen / Vereine und Verbände Leistungsangebot Eckdaten  Business IT Alignment  Gründung 1990  Business Information Management  400 Mitarbeiter  Business Process Management  8 Standorte  Anwendungsentwicklung  SOA und System-Integration  IT-Infrastruktur-Management © OPITZ CONSULTING GmbH 2012 Seite 3
  • 4.
  • 6. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarer mobiler JavaScript Web-Apps
  • 7. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarer mobiler JavaScript Web-Apps
  • 8. In diesem Vortrag geht‘s um ... ... die Entwicklung testbarer und wartbarer mobiler JavaScript Web-Apps
  • 10.
  • 12. "Multi Page Web App" Browser Server HTML-Page Model View Data Backend UI Values Controller
  • 13. "AJAX Web App" Browser Server Change Model AJAX- View Ba Data Engine Controller Events
  • 14. "Single Page Web App" Browser Server Model View Data Backend Controller
  • 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. <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
  • 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> <fieldset data-role="controlgroup"> <input type="checkbox" id="todo1"/> <label for="todo1">create a mobile todo app</label> </fieldset> </div> </div> jQuery Mobile Markup
  • 24. <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
  • 25. <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
  • 26. Two Way Data Binding
  • 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. $('#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>'; }
  • 35. $('#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>'; }
  • 36. Das Ziel sollte aber sein: function TodoController() { this.todos = []; this.inputText = ''; this.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; }; }
  • 37. Angular JS Declarative MVC with UI Templates Dependency Injection Two-Way Framework Data Binding http://angularjs.org/#/
  • 38. Two-Way Databinding read read write Data- write DOM Controller binding watch watch
  • 39. Scopes Scope Expressions $get(<expr>) 'inputText' 'todos.length' $set(<expr>, <value>) ... $watch(<expr>, <callback>)
  • 40. Demo
  • 41. Das Ziel ... function TodoController() { this.todos = []; this.inputText = ''; this.addTodo = function() { this.todos.push({ name: this.inputText, done: false }); this.inputText = ''; }; }
  • 42. Mit Angular ... function TodoController($scope) { $scope.todos = []; $scope.inputText = ''; $scope.addTodo = function() { $scope.todos.push({ name: $scope.inputText, done: false }); $scope.inputText = ''; }; } TodoController.$inject = ['$scope'];
  • 43. <div data-role="page" TodoController-Scope ng-controller="TodoController"> inputText: 'new todo' erzeugt <input type="text" todos: [...] bindet ng-model="inputText" bindet <div ng-repeat="todo in todos"> erzeugt Repeater Scope Repeater Scope Repeater Scope todo: { todo: todo: { { <input type="checkbox" ng-model="todo.done"/> done: false done: false done: false bindet name: 'makemoney' name: 'makemoney' name: 'makemoney' <label> {{todo.name}} } </label> bindet }}
  • 44. jQuery Mobile und AngularJS Das Problem: Die DOM-Manipulationen von jQuery Mobile und AngularJS müssen koordiniert werden!
  • 45. jQuery Mobile und AngularJS Die Lösung: jQuery Mobile Angular Adapter
  • 46. jQuery Mobile Angular Adapter Koordination von jQuery Mobile und AngularJS Erweiterungen für mobile Web-Apps Open Source unter https://github.com/tigbro/ jquery-mobile-angular-adapter
  • 48. Dependency Injection ist ein Entwurfsmuster und dient dazu, die Abhängigkeiten zwischen Komponenten zu minimieren. Es überträgt die Verantwortung für das Erzeugen und die Verknüpfung von Objekten an ein extern konfigurierbares Framework http://de.wikipedia.org/wiki/Dependency_Injection
  • 49. Dependency Injection ist ein Entwurfsmuster und dient dazu, die Abhängigkeiten zwischen Komponenten zu minimieren. Es überträgt die Verantwortung für das Erzeugen und die Verknüpfung von Objekten an ein extern konfigurierbares Framework http://de.wikipedia.org/wiki/Dependency_Injection
  • 50. Beispiel: Backend-Anbindung function refreshTodos() { var self = this; read('ToDoApp', function(response) { self.todos = response; }); }
  • 51. Beispiel: Backend-Anbindung function refreshTodos() { var self = this; read('ToDoApp', function(response) { self.todos = response; }); }
  • 52. Beispiel: Backend-Anbindung 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. Beispiel: Backend-Anbindung 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. Beispiel: Backend-Anbindung var readUrl = 'https://secure.openkeyval.org/'; function read(key, success) { var url = readUrl + key; waitdialog.show(); jsonp(url, function(data) { success(data); waitdialog.hide(); }); }
  • 55. Beispiel: Backend-Anbindung waitDialog todoController todoStore key value key value key value ... ... refreshTodos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created by Factories
  • 56. Beispiel: Backend-Anbindung waitDialog todoController todoStore key value key value key value ... ... refreshTodos ... read ... todoStore waitDialog jsonp jsonp key value ... ... created by Dependency Injection
  • 57. Angular JS Declarative MVC with UI Templates Dependency Injection Two-Way Framework Data Binding http://angularjs.org/#/
  • 58. Services und DI mit Angular function jsonpFactory() { // returns jsonp function // ... } function waitdialogFactory() { // returns waitdialog object // ... }
  • 59. Services und DI mit Angular var module = angular.module("todo", []);
  • 60. Services und DI mit Angular var module = angular.module("todo", []); module.factory('jsonp', jsonpFactory); module.factory('waitdialog', waitdialogFactory);
  • 61. Services und DI mit Angular var module = angular.module("todo", []); module.factory('jsonp', jsonpFactory); module.factory('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { // use jsonp, waitdialog here } return { read: read }; }
  • 62. Services und DI mit Angular var module = angular.module("todo", []); module.factory('jsonp', jsonpFactory); module.factory('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { function read(key, success) { // use jsonp, waitdialog here } return { read: read }; } todoStoreFactory.$inject = ['jsonp', 'waitdialog'];
  • 63. Services und DI mit Angular var module = angular.module("todo", []); module.factory('jsonp', jsonpFactory); module.factory('waitdialog', waitdialogFactory); function todoStoreFactory(jsonp, waitdialog) { // ... } todoStoreFactory.$inject = ['jsonp', 'waitdialog']; module.factory('todoStore', todoStoreFactory);
  • 64. Controller und DI mit Angular function TodoController($scope, todoStore) { ... } TodoController.$inject = ['$scope', 'todoStore']; module.controller("rylc.TodoController", TodoController);
  • 65. Controller und DI mit Angular function TodoController($scope, todoStore) { ... } TodoController.$inject = ['$scope', 'todoStore']; module.controller("rylc.TodoController", TodoController);
  • 66. Controller und DI mit Angular function TodoController($scope, todoStore) { ... } TodoController.$inject = ['$scope', 'todoStore']; module.controller("rylc.TodoController", TodoController);
  • 67. jQuery Mobile Angular Adapter Koordination von jQuery Mobile und AngularJS Erweiterungen für mobile Web-Apps Open Source unter https://github.com/tigbro/ jquery-mobile-angular-adapter
  • 68. jQuery Mobile Angular Adapter Mobile Events
  • 69. <div id="welcomePage" data-role="page" ngm-pagebeforeshow="rental.prefetchMasterData()" ngm-pagebeforehide="rental.clearMessages()"> ... </div>
  • 70. <div id="welcomePage" data-role="page" ngm-pagebeforeshow="rental.prefetchMasterData()" ngm-pagebeforehide="rental.clearMessages()"> ... </div> Unterstütze Events: vclick swipe pagebeforeshow swiperight pageshow swipeleft pagebeforehide tap pagehide taphold
  • 71. jQuery Mobile Angular Adapter Shared Controller
  • 72. LoginPage <div id="loginPage" Scope ng-controller="LoginController"> login <a ngm-click="login()">
  • 73. LoginPage <div id="loginPage" Scope ng-controller="LoginController"> login <a ngm-click="login()"> <div id="welcomePage" WelcomePage ng-controller="WelcomeController"> Scope logout <a ngm-click="logout()">
  • 74. LoginPage <div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="login()"> login logout <div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController"> auth <a ngm-click="logout()">
  • 75. LoginPage <div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout <div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController"> auth <a ngm-click="auth.logout()">
  • 76. LoginPage <div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout <div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController, "rental:RentalController"> auth <a ngm-click="auth.logout()"> rental <a ngm-click="rental.initRental()"> Rental- Controller Scope initRental searchCar
  • 77. LoginPage <div id="loginPage" Scope ngm-shared-controller= Authentication- "auth:AuthenticationController"> auth Controller Scope <a ngm-click="auth.login()"> login logout <div id="welcomePage" WelcomePage ngm-shared-controller= Scope "auth:AuthenticationController, "rental:RentalController"> auth <a ngm-click="auth.logout()"> rental <a ngm-click="rental.initRental()"> Rental- <div id="rentalPage" Controller Scope ngm-shared-controller= RentalPage "auth:AuthenticationController, Scope initRental "rental:RentalController"> searchCar auth <a ngm-click="rental.searchCars()"> rental
  • 78. jQuery Mobile Angular Adapter Wait Dialog
  • 80. jQuery Mobile Angular Adapter Paging / Load More
  • 81.
  • 82. <fieldset ng-repeat="todo in todos | paged:'pager':5"> <input type="checkbox" ng-model="todo.done" id="checked"> <label for="checked">{{todo.name}}</label> </fieldset> <div ngm-if="pager.hasMore"> <a href="#" ngm-click="pager.loadMore()" data-role="button"> Load more </a> </div>
  • 83. <fieldset ng-repeat="todo in todos | paged:'pager':5"> <input type="checkbox" ng-model="todo.done" id="checked"> <label for="checked">{{todo.name}}</label> </fieldset> <div ngm-if="pager.hasMore"> <a href="#" ngm-click="pager.loadMore()" data-role="button"> Load more </a> </div>
  • 84. Fazit Auch bei der Entwicklung von JavaScript Clients sollten geeignete Entwurfsmuster angewendet werden!
  • 85. Fazit Bibliotheken und Frameworks helfen bei der Umsetzung!
  • 86. Fazit Eine praxiserprobte Kombination für die Entwicklung mobiler Web-Apps: jQuery Mobile + AngularJS + Adapter
  • 87. 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/
  • 88. Vielen Dank für Ihr Interesse! @tigbro