DDAY2014 - Costruire una app mobile con Ionic, AngularJS ed ovviamente Drupal

85

description

Speaker: Michel Morelli Area: Development Il talk verterà sulla creazione di una semplice app mobile che sfrutti il framework ionic per quello che riguarda l'accesso al mobile, il MVVM AngualarJS per quello che concerne il collegamento tra mobile e Drupal ed il modulo Service per quello che riguarda il reperimento delle informazioni lato Server.

Transcript of DDAY2014 - Costruire una app mobile con Ionic, AngularJS ed ovviamente Drupal

Costruire una app mobile con Ionic, AngularJS ed ovviamente Drupal

Chi sono

Chi sono

Davide Michel [email protected]

Chi sono

Davide Michel [email protected]

Programmatore PHP Senior, Drupal Senior e DBA MySQL

Chi sono

Davide Michel [email protected]

Programmatore PHP Senior, Drupal Senior e DBA MySQLSviluppatore Web AngularJS, MongoDB (da poco) e NodeJS

Chi sono

Davide Michel [email protected]

Programmatore PHP Senior, Drupal Senior e DBA MySQLSviluppatore Web AngularJS, MongoDB (da poco) e NodeJSSviluppatore Mobile su piattaforma HTML/CSS/JS

Iniziamo

Cos'è Drupal

Cos'è Drupal

Veramente ??? No dai :D

Drupal: Services

Drupal: Services

Si installa nel solito modo

Drupal: Services

Si installa nel solito modoSi deve creare quello che si chiama Rest point

Drupal: Services

Si installa nel solito modoSi deve creare quello che si chiama Rest point

Maggiore diversificazione delle risorse

Drupal: Services

Si installa nel solito modoSi deve creare quello che si chiama Rest point

Maggiore diversificazione delle risorse All'interno della configurazione di services si possono dare i

permessi di accesso per i singoli servizi

Drupal: Services

Drupal: Services

Si installa nel solito modoSi deve creare quello che si chiama Rest point

Maggiore diversificazione delle risorse All'interno della configurazione di services si possono dare i permessi

di accesso per i singoli servizi Attenzione: i permessi per accedere alla funzionalità del servizio

non sono i permessi di accesso di Drupal. Vanno configurati anche questi

Altrimenti si avranno degli accessi negati senza capire il perché.

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversi

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversiCreiamo la nostra funzione che risponde in JSON

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversiCreiamo la nostra funzione che risponde in JSONUtilizziamo views_datasource che risponde in JSON

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversiCreiamo la nostra funzione che risponde in JSONUtilizziamo views_datasource che risponde in JSONUtilizziamo Services che consente i CRUD

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversiCreiamo la nostra funzione che risponde in JSONUtilizziamo views_datasource che risponde in JSONUtilizziamo Services che consente i CRUD

In Drupal Services i nodi si possono creare chiamando direttamente il servizio /node

Drupal: Services

Per le applicazioni mobili ci servono le chiamate che ritornino del JSON Perché è la soluzioni più pratica.

Drupal può rispondere in 3 modi diversiCreiamo la nostra funzione che risponde in JSONUtilizziamo views_datasource che risponde in JSONUtilizziamo Services che consente i CRUD

In Drupal Services i nodi si possono creare chiamando direttamente il servizio /nodeLa struttura deve essere come se lo stessi creando via PHP.

Title, Type, Body sono valori normali (nessuno nota l'errore?)Un FIELD è invece nella struttura: { 'und' : [ { value: ILVALORE } ]}

che corrisponde a [LANGUAGE_NONE][0][value]

Drupal: Services

Attenzione nello sviluppo nella fase di debug:Access-Control-Allow-Origin(https://github.com/systemseed/services_accept_origin)

Plugin per Chrome:“Allow-Control-Allow-Origin”

Questo problema c'è solo sui browser perché sugli smartphone l'accessoavviene da file:// e non http://

Consiglio:Testare su un device fisico è sempre meglio. Si hanno le vere risposte delle performance e si può fare il debug

dell'html tramite chrome://inspect

AngularJS

AngularJS

E' un MVC

AngularJS

E' un MVCO meglio un MVVM perché c'è il doppio binding

AngularJS

E' un MVCO meglio un MVVM perché c'è il doppio bindingSviluppato da Google

AngularJS

E' un MVCO meglio un MVVM perché c'è il doppio bindigSviluppato da GooglePermette di spostare la logica di funzionamento di un framework direttamente sul frontend

AngularJS

E' un MVCO meglio un MVVM perché c'è il doppio bindigSviluppato da GooglePermette di spostare la logica di funzionamento di un framework direttamente sul frontendPensato per creare SAP: Singe Application Page

AngularJS

E' un MVCO meglio un MVVM perché c'è il doppio bindigSviluppato da GooglePermette di spostare la logica di funzionamento di un framework direttamente sul frontendPensato per creare SAP: Singe Application PageMa lo si può usare in tanti modi

IonicFramework

IonicFramework

All'inizio c'erano le applicazioni che venivano create con il linguaggio dello smartphone

IonicFramework

All'inizio c'erano le applicazioni che venivano create con il linguaggio dello smartphonePoi si è pensato di utilizzare il web per creare delle piccole pagine a modo di applicazione ed è stato inventato jQueryMobile

IonicFramework

All'inizio c'erano le applicazioni che venivano create con il linguaggio dello smartphonePoi si è pensato di utilizzare il web per creare delle piccole pagine a modo di applicazione ed è stato inventato jQueryMobilePoi c'è stato Phonegap (diventato poi cordova, ma rimasto anche Phonegap) che ha permesso di creare delle specie di applicazioni native che sfruttano il browser

IonicFramework

All'inizio c'erano le applicazioni che venivano create con il linguaggio dello smartphonePoi si è pensato di utilizzare il web per creare delle piccole pagine a modo di applicazione ed è stato inventato jQueryMobilePoi c'è stato Phonegap (diventato poi cordova, ma rimasto anche Phonegap) che ha permesso di creare delle specie di applicazioni native che sfruttano il browserPhonegap/Cordova fornisce solo l'accesso alla risorsa dello smartphone all'interno del browser

TastieraVibrazioneFotocameraFilesystemAltro...

IonicFramework

JqueryMobile ha però il concetto di unica pagina dove tutto deve essere visualizzato e poi nascosto

IonicFramework

JqueryMobile ha pero' il concetto di unica pagina dove tutto deve essere visualizzato e poi nascostoAngular ha il concetto di “vista” che può essere riempita a seconda di quello che si vuole visualizzare

IonicFramework

JqueryMobile ha pero' il concetto di unica pagina dove tutto deve essere visualizzato e poi nascostoAngular ha il concetto di “vista” che puo' essere riempita a secondo di quello che si vuole visualizzare Sullo smartphone (meno memoria, meno potenza di calcolo) è molto meglio visualizzare poco alla volta

IonicFramework

JqueryMobile ha pero' il concetto di unica pagina dove tutto deve essere visualizzato e poi nascostoAngular ha il concetto di “vista” che puo' essere riempita a secondo di quello che si vuole visualizzare Sullo smartphone (meno memoria, meno potenza di calcolo) è molto meglio visualizzare poco alla volta

Quindi come unire mobile, user interface e applicazioni native ?

IonicFramework

IonicFramework prende Cordova e lo unisce ad Angular ampliandoli

IonicFramework

IonicFramework prende Cordova e lo unisce ad Angular ampliandoli

Accesso al dispositivo (cordova)

IonicFramework

IonicFramework prende Cordova e lo unisce ad Angular ampliandoli

Accesso al dispositivo (cordova)Gestione della visualizzazione, del reperimento dei dati (angularjs)

IonicFramework

IonicFramework prende Cordova e lo unisce ad Angular ampliandoli

Accesso al dispositivo (cordova)Gestione della visualizzazione, del reperimento dei dati (angularjs)Attività normali dello smartphone rese disponibili

IonicFramework

Via JS

Slide menuTabSwipeRouting per le pagine interneFinestre modaliFinestre di loading (spinner)

IonicFramework

Via CSSSlidesListsBottoniHeaderFooter

IonicFramework

Come fare le chiamate con Ionic, o meglio via AngularJS:

3 alternative praticabili$http$resourceRestangular

Sono messe in ordine di “livello di programmazione”. Dal più basso al più alto.

IonicFramework

Per questo talk ho usato Restangular, anche se ci sono cose che non mi piacciono:

Il risultato della chiamata viene restituito come oggettoRestangularMa quello che abbiamo richiesto è messo allo stesso livello delle funzioni native.Quindi se riceviamo un array di informazioni non possiamo utilizzare angular.forEach() perché andremmo a prendere anche le funzioni native.

IonicFramework

Per questo talk ho usato Restangular, anche se ci sono cose che non mi piacciono:

Il risultato della chiamata viene restituito come oggetto RestangularMa quello che abbiamo richiesto è messo allo stesso livello delle funzioni native.Quindi se riceviamo un array di informazioni non possiamo utilizzare angular.forEach() perché andremmo a prendere anche le funzioni native.

Per usarlo con drupal è necessario modificarne il funzionamento (tramite apposita funzione addResponseInterceptor, nessuna modifica al codice di Restangular) perché Services ritorna una serie di oggetti, mentre Restangular vuole un elemento solo oppure un array.

IonicFramework

Per questo talk ho usato Restangular, anche se ci sono cose che non mi piacciono:

Il risultato della chiamata viene restituito come oggetto RestangularMa quello che abbiamo richiesto è messo allo stesso livello delle funzioni native.Quindi se riceviamo un array di informazioni non possiamo utilizzare angular.forEach() perché andremmo a prendere anche le funzioni native.

Per usarlo con drupal è necessario modificarne il funzionamento (tramite apposita funzione addResponseInterceptor, nessuna modifica al codice di Restangular) perché Services ritorna una serie di oggetti, mentre Restangular vuole un elemento solo oppure un array.

Per un altro progetto ho usato $http. Meno funzioni evolute, ma più usabile

IonicFramework

Vediamo come IonicFramework gestisce le varie “view”.

Prima di tutto il file principale: INDEX.HTML

IonicFramework<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title>"Utrend"</title>

<!-- build:css styles/vendor.css --> <!-- <link rel="stylesheet" href="vendor/some.contrib.css"> --> <!-- bower:css --> <link rel="stylesheet" href="lib/ionic/release/css/ionic.css" /> <!-- endbower --> <!-- endbuild -->

<!-- build:css({.tmp,app}) styles/main.css --> <link rel="stylesheet" href="styles/main.css"> <!-- endbuild --> </head>

<body ng-app="Utrend"> <ion-nav-view></ion-nav-view>

<!-- build:js scripts/vendor.js --> <!-- <script src="vendor/someContribJs.js"></script> --> <!-- bower:js --> <script src="lib/angular/angular.js"></script> <script src="lib/angular-animate/angular-animate.js"></script> <script src="lib/angular-sanitize/angular-sanitize.js"></script> <script src="lib/angular-ui-router/release/angular-ui-router.js"></script> <script src="lib/collide/collide.js"></script> <script src="lib/ionic/release/js/ionic.js"></script> <script src="lib/ionic/release/js/ionic-angular.js"></script> <!-- endbower --> <!-- endbuild -->

IonicFramework <!-- cordova script (this will be a 404 during development) --> <script src="cordova.js"></script>

<!-- build:js scripts/scripts.js --> <script src="scripts/common/angular-cookie.min.js"></script> <script src="scripts/common/underscore-min.js"></script> <script src="scripts/common/restangular.min.js"></script>

<script src="scripts/config.js"></script> <script src="scripts/app.js"></script> <script src="scripts/controllers.js"></script>

<script src="scripts/common/restfulServices.js"></script> <script src="scripts/common/sharedService.js"></script> <script src="scripts/user/loginCtrl.js"></script> <script src="lib/sweetalert/lib/sweet-alert.min.js"></script> <link rel="stylesheet" href="lib/sweetalert/lib/sweet-alert.css"> <script src="scripts/posts/picture.js"></script> <script src="scripts/posts/singlePostCtrl.js"></script> <script src="scripts/homeCtrl.js"></script> <!-- endbuild --></body></html>

L'unico motivo per modificare questo file è per inserire i vari SCRIPT dei nostri controller

IonicFramework

Ed il file che gestisce le view: app.js

'use strict';// Ionic Starter App, v0.9.20

// angular.module is a global place for creating, registering and retrieving Angular modules// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)// the 2nd parameter is an array of 'requires'angular.module('Utrend', ['ionic', 'config', 'Utrend.controllers','restangular','ipCookie'])

.run(function($ionicPlatform) { $ionicPlatform.ready(function() { // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard // for form inputs) if(window.cordova && window.cordova.plugins.Keyboard) { cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); } if(window.StatusBar) { // org.apache.cordova.statusbar required StatusBar.styleDefault(); } });})

IonicFramework

Ed il file che gestisce le view: app.js

.config(function($stateProvider, $urlRouterProvider,$compileProvider,RestangularProvider) { $stateProvider

.state('app', { url: '/app', abstract: true, templateUrl: 'templates/menu.html', controller: 'AppCtrl' }) .state('app.home', { url: '/home', views: { 'menuContent' :{ templateUrl: 'templates/home.html', controller : 'homeCtrl' } } })

.state('app.login', { url: '/login', controller: 'loginCtrl' }) })

IonicFramework

Ed il file che gestisce le view: app.js

.state('app.browse', { url: '/browse', views: { 'menuContent' :{ templateUrl: 'templates/browse.html', controller: 'singlePostCtrl' } } }) .state('app.getPicture', { url: '/getpicture', views: { 'menuContent' :{ templateUrl: 'templates/getPicture.html', controller: 'pictureCtrl' } } });

IonicFramework

Ed il file che gestisce le view: app.js

// if none of the above states are matched, use this as the fallback $urlRouterProvider.otherwise('/app/home'); $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/); RestangularProvider.setBaseUrl('http://MYDOMAIN/'); RestangularProvider.setResponseExtractor(function(response) { var newResponse = response; newResponse.originalElement = angular.copy(response); return newResponse; });});

Drupal Service + IonicFramework

Per collegarci a Drupal abbiamo detto che utilizzeremo Services

Drupal Service + IonicFramework

Per collegarci a Drupal abbiamo detto che utilizzeremo ServicesMa dobbiamo prestare attenzione ad una cosa molto importante: il token CSRF

Drupal Service + IonicFramework

Per collegarci a Drupal abbiamo detto che utilizzeremo ServicesMa dobbiamo prestare attenzione ad una cosa molto importante: Il token CSRFE' stato aggiunto dalla versione 3.5 del modulo services

Drupal Service + IonicFramework

Per collegarci a Drupal abbiamo detto che utilizzeremo ServicesMa dobbiamo prestare attenzione ad una cosa molto importante: Il token CSRFE' stato aggiunto dalla versione 3.5 del modulo servicesLega a doppio mandato la sessione attuale con quella registrata sul serverPer fare qualsiasi operazione che non sia un GET è richiesto questo TOKEN negli header della richiesta

Drupal Service + IonicFramework

Per collegarci a Drupal abbiamo detto che utilizzeremo ServicesMa dobbiamo prestare attenzione ad una cosa molto importante: Il token CSRFE' stato aggiunto dalla versione 3.5 del modulo servicesLega a doppio mandato la sessione attuale con quella registrata sul serverPer fare qualsiasi operazione che non sia un GET è richiesto questo TOKEN negli header della richiestaPer rendere il codice scritto più gestibile e leggibile è consigliabile creare un service di angular che gestisca per noi le connessioni

Drupal Service + IonicFramework

(function () {

angular.module('MyM').service('restfulService',['ipCookie','Restangular','$q',restfulService]);

var tokenVar = '';

function restfulService(ipCookie,Restangular,$q) {//Qui le chiamate REST

return { //Setta la directory di partenza del service rest. In questo modo non devo sempre definirlo restfulBase : function() { return Restangular.oneUrl('rest','http://MioDominio/rest'); }, }

})();

Drupal Service + IonicFramework

Prendiamo il token

getToken : function(reset) { if (tokenVar != '' && !reset) { var deferred = $q.defer(); deferred.resolve(tokenVar); return deferred.promise } return Restangular.oneUrl('services/session/token','http://MIODOMINIO/services/session/token').get().then(function (token) { tokenVar = token; return token; });},

Notate come non abbia utilizzato restfulBase ma solamente per unaquestione di demo

Drupal Service + IonicFramework

E' facile creare una app che permetta di gestire gli utenti collegati e quelli non collegati (anonimi)

Drupal Service + IonicFramework

E' facile creare una app che permetta di gestire gli utenti collegati e quelli non collegati (anonimi)

Per farlo utilizzeremo AngularJS e il suo ng-if modificando il file di template del menù slide

Drupal Service + IonicFramework<ion-side-menus>

<ion-pane ion-side-menu-content drag-content="false"> <ion-nav-bar class="bar-positive"> <!--<ion-nav-back-button class="button-clear"><i class="icon ion-ios7-arrow-back"></i> Back</ion-nav-back-button>--> </ion-nav-bar> <ion-nav-view name="menuContent" animation="slide-left-right"></ion-nav-view> </ion-pane>

<ion-side-menu side="left"> <header class="bar bar-header bar-stable"> <h1 class="title">Left</h1> </header> <ion-content class="has-header"> <ion-list ng-if="user.uid == 0"> <ion-item nav-clear menu-close ng-controller="loginCtrl" ng-click="login()"> Login </ion-item> </ion-list>

Drupal Service + IonicFramework <ion-list ng-if="user.uid > 0">

<ion-item nav-clear menu-close > Hi, {{user.name}} </ion-item> <ion-item nav-clear menu-close > MyPage </ion-item> <ion-item nav-clear menu-close href="#/app/getpicture"> upload photo </ion-item> <ion-item nav-clear menu-close href="#/app/browse"> Browse </ion-item>

<ion-item nav-clear menu-close href="#/app/search"> Search </ion-item>

<ion-item nav-clear menu-close ng-controller="loginCtrl" ng-click="logout()"> Logout </ion-item>

</ion-list> </ion-content> </ion-side-menu></ion-side-menus>

Drupal Service + IonicFrameworkVediamo il controller per il login (notate cosa usa)

/** * Created by ziobudda on 05/11/14. */

(function () { angular.module('Utrend').controller('loginCtrl',['$scope','$ionicModal','$state','sharedService','restfulService','$rootScope', loginCtrl]);

function loginCtrl($scope, $ionicModal,$state,sharedService,restfulService,$rootScope) { $scope.error_message = '';

sharedService.getToken();

// Form data for the login modal $scope.loginData = {};

// Create the login modal that we will use later $ionicModal.fromTemplateUrl('templates/login.html', { scope: $scope }).then(function(modal) { $scope.modal = modal; });

// Triggered in the login modal to close it $scope.closeLogin = function() { $scope.modal.hide(); },

Drupal Service + IonicFramework

// Open the login modal $scope.login = function() { $scope.modal.show(); };

// Perform the login action when the user submits the login form $scope.doLogin = function() { console.log('Doing login22', $scope.loginData);

restfulService.login($scope.loginData) .then(function(result) { $rootScope.$broadcast("login",{user: result.user}); restfulService.getToken(true).then(function(result) { $scope.closeLogin(); swal({title: "Login OK", text: "Now you are a loggedin user!", type: "success"}); $state.go('app.browse') })

}, function (result) { $scope.error_message = result.data[0];

}); }

Drupal Service + IonicFramework

$scope.logout = function () { restfulService.logout() .then(function(result) { sharedService.user = {}; sharedService.user.uid = 0; swal({title: "Logout OK", text: "Now you are a logged out user!", type: "success"}); $rootScope.$broadcast("logout"); $state.go("app.home"); }); }

};

})();

Drupal Service + IonicFramework

In questo controller abbiamo:

Le finestre modali (per chiedere login e password)

Drupal Service + IonicFramework

In questo controller abbiamo:

Le finestre modali (per chiedere login e password)

La gestione automatica del menù slide fatto tramite una semplice valorizzazione di sharedService.user

Drupal Service + IonicFramework

E per visualizzare dei dati presi via GET ? Nella nostra app di prova sonodelle immagini

Il controller è puro AngularJS

Drupal Service + IonicFramework

E per visualizzare dei dati presi via GET ? Nella nostra app di prova sonodelle immagini

Il controller è puro AngularJS

Al div principale sono state definite le funzioni per gestire swipe a sinistra swipe a destra

<div on-swipe-left="onSwipeLeft()" on-swipe-right="onSwipeRight()" >

E' IonicFramework che rende facilmente disponibile il service $swipe di AngularJS

https://docs.angularjs.org/api/ngTouch/service/$swipe

Drupal Service + IonicFrameworkIl codice HTML alla base della visualizzazione delle nostre immagini:

<ion-view title="Browse"> <ion-nav-buttons side="left" class="bar-positive"> <button menu-toggle="left"class="button button-icon icon ion-android-contact"></button> </ion-nav-buttons> <ion-content class="has-header"> <div on-swipe-left="onSwipeLeft()" on-swipe-right="onSwipeRight()" >

<div class="item item-body"> <img class="full-image" ng-src="{{post.fullimage}}"> <p> {{post.body.und[0].value}} </p> <p> <a href="#" class="subdued">{{post.like_count}} Like</a> <a href="#" class="subdued">{{post.comment_count}} Comments</a> </p> </div>

<div class="item tabs tabs-secondary tabs-icon-left"> <a class="tab-item" href="#"> <i class="icon ion-thumbsup"></i> Like </a> <a class="tab-item" href="#"> <i class="icon ion-chatbox"></i> Comment </a> <a class="tab-item" href="#"> <i class="icon ion-share"></i> Share </a> </div>

</div> </ion-content></ion-view>

Drupal Service + IonicFrameworkE questo è il controller

(function () { angular.module('Utrend').controller('singlePostCtrl', ['$scope','$ionicLoading', '$timeout', 'sharedService', 'restfulService', '$rootScope', singlePostCtrl]);

function singlePostCtrl($scope, $ionicLoading, $timeout, sharedService, restfulService, $rootScope) { $scope.searchParams = {from : sharedService.fromPost, limit : 1};

if (typeof $scope.post == 'undefined') { console.log("Azzero $scope.post"); $scope.post = {}; } $scope.getPost = function () { return restfulService.postSearch($scope.searchParams) .then(function(result) { sharedService.log("postSearch",result); return result; }) }

//Questo prende il primo post quando viene instanziato questo controller restfulService.getToken().then(function (result) { $ionicLoading.show({template: '<i class="button-icon icon ion-loading-a"></i>'}); $scope.getPost().then(function (result) { $scope.post = result.value[0]; sharedService.log("post",$scope.post); $timeout(function() { $scope.$apply(); $ionicLoading.hide(); }); }); });

Drupal Service + IonicFramework

$scope.onSwipeLeft = function() { console.log("onSwipeLeft"); $scope.searchParams.from++; sharedService.fromPost = $scope.searchParams.from; console.log($scope.searchParams.from); $ionicLoading.show({template: '<i class="button-icon icon ion-loading-a"></i>'}); $scope.getPost().then(function (result) { console.log("getToken -> getPost"); $scope.post = result.value[0]; sharedService.log("post",$scope.post); $timeout(function() { $scope.$apply(); $ionicLoading.hide(); }); }); }

Drupal Service + IonicFramework $scope.onSwipeRight = function() { console.log("onSwipeRight"); $scope.searchParams.from = ($scope.searchParams.from == 1) ? 0 : ($scope.searchParams.from-1); sharedService.fromPost = $scope.searchParams.from; console.log($scope.searchParams.from); $ionicLoading.show(); $scope.getPost().then(function (result) { console.log("getToken -> getPost"); $scope.post = result.value[0]; sharedService.log("post",$scope.post); $timeout(function() { $scope.$apply(); $ionicLoading.hide(); }); }); } }})();

Riassumendo

Per creare applicazioni mobili che sfruttano l'html5:

AngularJS IonicFramework (per velocizzare lo sviluppo) Un servizio remoto che permetta di ricevere le informazioni da visualizzare in formato JSON

Domande ?

Solo se conosco la risposta, per favore :D

Link utili

AngularJS: https://angularjs.org/

IonicFramework: http://ionicframework.com/

IonicFramework Generator: https://github.com/diegonetto/generator-ionic

La mia rivista flipboard dedicata ad angularJS e gli altri JShttps://flipboard.com/section/angularjs%2C-nodejs-e-gli-altri-js-bTb8rt

Icone per le app: http://ionicons.com/

Usare FontAwesome (Bootstrap): http://blog.nraboy.com/2014/10/

use-font-awesome-glyph-icons-ionicframework/

Grazie!