Construyendo apps de tiempo real con

@HybridAppsCol

Hybrid Apps Colombia

Nuestros patrocinadores

Conferencista

(@nicobytes)
Nicolas Molina Monroy


Desarrollador de aplicaciones web y móviles utilizando tecnologías híbridas


Actualmente trabajando para un estudio digital, con énfasis en el desarrollo de Software.

Ionicframework + Firebase

 

Aprende a trabajar con estas dos increíbles tecnologías para desarrollar tu aplicación móvil.

 

Conocerás cómo integrar bases de datos NoSql con firebase, haciendo que tu aplicación tenga conexión en tiempo real con tus datos

Antes de empezar

Visión general

Evolución de las aplicaciones web

Evolución de las aplicaciones web

Evolución de las aplicaciones hibridas

Evolución de las aplicaciones hibridas

¿Que es un BaaS?

Un Backend as a Service, es un modelo de servicio para otorgar a desarrolladores WEB Y  de App Moviles una forma de vincular sus apps con almacenamiento y servicios analíticos entre otros

Back-end

Velocidad

Seguridad

Auntenticación

Persistencia

Presentamos a

El Back-end en tiempo real para tu APP

Resultado

  1. Bases de datos NoSQL

  2. Uso intensivo de JSON

  3. Realtime

  4. Offline

  5. Multiplataforma

  6. RESTful API

  7. Todas las anteriores...

  8. Y mas...

Presentamos a

Aplicaciones hibridas

  1. Podemos utilizar nuestros conocimientos web en HTML, JS Y CSS
  2. Corren en un Webview 
  3. Se conectan a las partes nativas por medio de cordova
  4. Una sola base de codigo

"Quiero un app nativa"

No siempre es lo adecuando

Desventajas de Nativo

  1. Conocimiento en cada plataforma

  2. Base de código totalmente independiente

  3. El desarrollo toma tiempo

  4. Decremento pobre

Todas las plataformas

Nuestro error más grande fue apostar 

demasiado en HTML5

El tiempo a pasado

Las capacidades de los dispositivos han cambiando rotundamente y el desarrollo front-end es otro totalmente diferente

Obsesionado por la rapidez

Basado en

Angular

Enfocado en

Nativo

Bello y personalizable

Un poderoso

CLI

Gran comunidad

Construido por NERDS (como tú)

Ionic Framework

Muéstrame el codigo

Manos a la obra

npm install -g cordova ionic

Instalamos ionic

//Nos basamos en un template
ionic start myApp blank
ionic start myApp tabs //para este ejemplo
ionic start myApp sidemenu

cd myApp
//Agregamos nuestras platformas
ionic platform add android
//Si quieres construir con sass (opcional)
ionic setup sass
//Para personalizar los iconos de tu app
ionic resources

Empezamos un proyecto

Agregamos Firebase

//Agregamos las librerías
ionic add firebase
ionic add angularfire
//Confirmamos
ionic list
//Ahora lo podemos correr
ionic serve
//Para ver el demo
ionic serve --lab

Ok bien

Se debe ver algo asi

Incluimos las librerias

<script src="lib/firebase/firebase.js"></script>
<script src="lib/angularfire/dist/angularfire.min.js"></script>
<script src="js/app.js"></script>

Antes del archivo app.js

La ruta

Este es el enlace entre nuestro controlador y vista

//la Ruta
.state('tab.todos', {
    url: '/todos',
    views: {
      'tab-todos': {
        templateUrl: 'templates/tab-todos.html',
        controller: 'TodosCtrl' //Recuerdenlo
      }
    }
  })
//Url por defecto
$urlRouterProvider.otherwise('/tab/todos');

La vista

Editamos las vistas (html)

//tabs.html
<ion-tab title="Tareas" icon="ion-checkmark" href="#/tab/todos">
  <ion-nav-view name="tab-todos"></ion-nav-view>
</ion-tab>

//tab-dash.html => tab-todos.html
<ion-view view-title="Tareas">
  <ion-content></ion-content>
</ion-view>

Necesitas iconos?

El controlador

//antes
.controller('DashCtrl', function($scope) {})

//Despues
.controller('TodosCtrl',[
  '$scope',
  function($scope){
    console.log('hi!');
  }
])

Resultado

Editamos nuestra Vista

<ion-view view-title="Tareas">
  <ion-content>
    <ion-list>
      <ion-item class="todo item item-icon-left" ng-repeat="todo in todos">
        <i class="icon ion-checkmark" ng-class="{'done': todo.done}"></i>
        <h2>{{ todo.name }}</h2>
        <p>{{ todo.text }}</p>
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

Recorremos una lista de tareas

Editamos nuestro Ctrl

Ponemos una lista de tareas de prueba

.controller('TodosCtrl',[
  '$scope',
  function($scope){
    $scope.todos = [
      {
        name:'Tarea 1',
        text : 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Asperiores odit incidunt beatae mollitia maiores error neque rem ipsa tenetur, sequi iste minima magnam, quis fuga! Quibusdam quo recusandae aut, aperiam.',
        done: true,
      },
      {
        name:'Tarea 2',
        text : 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Asperiores odit incidunt beatae mollitia maiores error neque rem ipsa tenetur, sequi iste minima magnam, quis fuga! Quibusdam quo recusandae aut, aperiam.',
        done: false,
      },
    ];
  }
])

Resultado

Variables por defecto

//El objeto
$scope.todo = {};
//La lista
$scope.todos = [];
//para editar o crear
$scope.is_new = true;

$ionicModal

Para el CRUD de la tarea ($ionicModal es un servicio)

$ionicModal.fromTemplateUrl('templates/todo-modal.html', {
      scope: $scope,
      animation: 'slide-in-up'
 }).then(function(modal) {
      $scope.modal = modal;
});

$scope.openModal = function() {
  $scope.modal.show();
};
$scope.closeModal = function() {
  $scope.modal.hide();
  $scope.todo = {};
  $scope.is_new = true;
};

Creamos el modal

Formulario para crear una tarea todo-modal.html

<ion-modal-view>
    <ion-header-bar>
	 <h1 class="title">Tarea</h1>
	  <button class="button" ng-click="closeModal()">Cerrar</button>
    </ion-header-bar>
    <ion-content>
	<form name="FormTodo" novalidate ng-submit="saveTodo()">
	   <div class="list">
	        <label class="item item-input item-stacked-label">
	          <span class="input-label">Nombre:</span>
	          <input type="text" ng-model="todo.name" required>
	        </label>
	        <label class="item item-input item-stacked-label">
	          <span class="input-label">Descripcion:</span>
	          <textarea rows="5" ng-model="todo.text" required></textarea>
	        </label>
	        <ion-toggle ng-model="todo.done" toggle-class="toggle-balanced">¿Hecho?</ion-toggle>
	    </div>
	    <div class="row">
	        <div class="col">
	           <button type="button" ng-show="!is_new" class="button button-block button-assertive" ng-click="deleteTodo()">Eliminar</button>
	        </div>
	        <div class="col">
	          <button type="submit" class="button button-block button-balanced" ng-disabled="FormTodo.$invalid">Guardar</button>
	        </div>
	   </div>
	</form>
    </ion-content>
</ion-modal-view>

Métodos para manejar el CRUD

Para el CRUD de la tarea


$scope.newTodo = function(){
    $scope.openModal();
}

$scope.editTodo = function(index){
  $scope.is_new = false;
  $scope.todo = $scope.todos[index];
  $scope.openModal();
}

$scope.addTodo = function(){
  console.log('addTodo');
  $scope.closeModal();
}

$scope.updateTodo = function(){
  console.log('updateTodo');
  $scope.closeModal();
}

$scope.deleteTodo = function(){
  console.log('deleteTodo');
  $scope.closeModal();
}

$scope.saveTodo = function(){
  if($scope.is_new){
    $scope.addTodo();
  }else{
    $scope.updateTodo();
  }
}

Actualizamos la vista

Con las nuevas acciones tabs-todos.hmtl

<ion-view view-title="Tareas">
  <ion-nav-buttons side="right">
    <button class="button" ng-click="newTodo()">Nueva</button>
  </ion-nav-buttons>
  <ion-content>
    <ion-list>
      <ion-item class="todo item item-icon-left" ng-repeat="todo in todos" ng-click="editTodo($index)">
        <i class="icon ion-checkmark" ng-class="{'done': todo.done}"></i>
        <h2>{{ todo.name }}</h2>
        <p>{{ todo.text }}</p>
      </ion-item>
    </ion-list>
  </ion-content>
</ion-view>

Respiramos

Ahora vamos con crear nuestra base de datos en firebase

Añadimos firebase como dependecia

angular.module('starter', [
  'ionic', 
  'firebase',
  'starter.controllers', 
  'starter.services'
])

Archivo app.js

Básico de angularfire

//Referencia a nuestra base de datos
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com/");

Dos tipos de respuesta:  Object o Array

var myObject = $firebaseObject(ref);
var myCollection = $firebaseArray(ref);

$firebaseObject$firebaseArray deben ser tratados como servicios en angular

Creamos nuestro Servicio

.factory('TodoFirebase',[
  '$firebaseArray','$firebaseObject',
  function($firebaseArray, $firebaseObject) {
    return {
      //retorna la referencia a la base de datos 'todos'
      allRef: function(){
        return new Firebase('https://todo-ionic-101.firebaseio.com/todos');
      },
      //La referencia la retorna como un array de firebase
      all: function(){
        return $firebaseArray(this.allRef());
      },
      //retorna la referencia  a un objeto 'todo'
      getRef: function(id){
        return new Firebase('https://todo-ionic-101.firebaseio.com/todos/' + id);
      },
      //La referencia la retorna como un objeto de firebase
      get: function(id){
        return $firebaseObject(this.getRef(id));
      }
    };
  }
])

Metodos de Firebase Crud

//Obtener las Tareas
$scope.todos = TodoFirebase.all();

//Crear Tarea
$scope.addTodo = function(){
  console.log('addTodo');
  $scope.todos.$add({
    name: $scope.todo.name,
    text: $scope.todo.text,
    done: $scope.todo.done || false
  });
  $scope.closeModal();
}

//Actualizar Tarea
$scope.updateTodo = function(){}
  console.log('updateTodo');
  var todo = TodoFirebase.getRef($scope.todo.$id);
  todo.update({
    name: $scope.todo.name,
    text: $scope.todo.text,
    done: $scope.todo.done || false
  });
  $scope.closeModal();
}

//Eliminar Tarea
$scope.deleteTodo = function(){
  console.log('deleteTodo');
  var todo = TodoFirebase.getRef($scope.todo.$id);
  todo.remove();
  $scope.closeModal();
}

Controlador

.controller('TodosCtrl',[
  '$scope','$ionicModal','TodoFirebase',
  function($scope, $ionicModal, TodoFirebase){
    $scope.todo = {};
    $scope.todos = TodoFirebase.all();
    $scope.is_new = true;

    $ionicModal.fromTemplateUrl('templates/todo-modal.html', {
      scope: $scope,
      animation: 'slide-in-up'
    }).then(function(modal) {
      $scope.modal = modal;
    });

    $scope.openModal = function() {
      $scope.modal.show();
    };
    $scope.closeModal = function() {
      $scope.modal.hide();
      $scope.todo = {};
      $scope.is_new = true;
    };

    $scope.newTodo = function(){
      $scope.openModal();
    }

    $scope.editTodo = function(index){
      $scope.is_new = false;
      $scope.todo = $scope.todos[index];
      $scope.openModal();
    }

    $scope.addTodo = function(){
      console.log('addTodo');
      $scope.todos.$add({
        name: $scope.todo.name,
        text: $scope.todo.text,
        done: $scope.todo.done || false
      });
      $scope.closeModal();
    }

    $scope.updateTodo = function(){
      console.log('updateTodo');
      var todo = TodoFirebase.getRef($scope.todo.$id);
      todo.update({
        name: $scope.todo.name,
        text: $scope.todo.text,
        done: $scope.todo.done || false
      });
      $scope.closeModal();
    }

    $scope.deleteTodo = function(){
      console.log('deleteTodo');
      var todo = TodoFirebase.getRef($scope.todo.$id);
      todo.remove();
      $scope.closeModal();
    }

    $scope.saveTodo = function(){
      if($scope.is_new){
        $scope.addTodo();
      }else{
        $scope.updateTodo();
      }
    }


  }
])

LISTO!!

Leer Varios Eventos

 

ref.on("child_added", function(snapshot, prevChildKey) {
  var newPost = snapshot.val();
  console.log("Author: " + newPost.author);
  console.log("Title: " + newPost.title);
  console.log("Previous Post ID: " + prevChildKey);
});

ref.on("child_changed", function(snapshot) {
  var changedPost = snapshot.val();
  console.log("The updated post title is " + changedPost.title);
});

ref.on("child_removed", function(snapshot) {
  var deletedPost = snapshot.val();
  console.log("The blog post titled '" + deletedPost.title + "' has been deleted");
});

Ahora solo es construir la app

ionic build

ionic upload

ionic share

¿Offline?

¿Preguntas?

Ahora si el refrigerio

 

Prestación basada en

Made with Slides.com