(@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.
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
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
Velocidad
Seguridad
Auntenticación
Persistencia
Bases de datos NoSQL
Uso intensivo de JSON
Realtime
Offline
Multiplataforma
RESTful API
Todas las anteriores...
Y mas...
Conocimiento en cada plataforma
Base de código totalmente independiente
El desarrollo toma tiempo
Decremento pobre
Nuestro error más grande fue apostar
demasiado en HTML5
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
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 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
Se debe ver algo asi
<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
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');
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>
//antes
.controller('DashCtrl', function($scope) {})
//Despues
.controller('TodosCtrl',[
'$scope',
function($scope){
console.log('hi!');
}
])
<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
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,
},
];
}
])
//El objeto
$scope.todo = {};
//La lista
$scope.todos = [];
//para editar o crear
$scope.is_new = true;
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;
};
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>
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();
}
}
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>
Ahora vamos con crear nuestra base de datos en firebase
angular.module('starter', [
'ionic',
'firebase',
'starter.controllers',
'starter.services'
])
Archivo app.js
//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 y $firebaseArray deben ser tratados como servicios en angular
.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));
}
};
}
])
//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();
}
.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();
}
}
}
])
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");
});