Nessa vídeo aula eu mostro como armazenar dados offline com o Ionic Storage.
O que é o Ionic Storage
O Ionic Storage é uma maneira simples de armazenar dados no formato chave/valor seja em um PWA (Progressive Web App) ou em um aplicativo nativo.
No aplicativo nativo será priorizado o uso do SQLite, para isso é necessário instalar o plugin cordova-sqlite-storage, e em um PWA a ordem de utilização será IndexedDB, WebSQL, e localstorage.
ionic cordova plugin add cordova-sqlite-storage
É possível escolher a ordem de prioridade de utilização de armazenamento. Para isso no arquivo app.module.ts, na propriedade imports basta colocar conforme exemplo abaixo.
import { IonicStorageModule } from '@ionic/storage'; @NgModule({ declarations: [...], imports: [ IonicStorageModule.forRoot({ name: '__mydb', driverOrder: ['indexeddb', 'sqlite', 'websql'] }) ], bootstrap: [...], entryComponents: [...], providers: [...] }) export class AppModule { }
Criando uma aplicação de exemplo
No vídeo acima e mostro como criar uma app para salvar contatos utilizando o Ionic Storage.
O passo a passo abaixo é o mesmo mostrado no vídeo.
- Passo 1: Criar o aplicativo.
- Passo 2: Instalar o Ionic Storage.
- Passo 3: Configurar o Ionic Storage.
- Passo 4: Criar o provider para fazer o CRUD.
- Passo 5: Criar a pagina de inclusão/alteração de contatos.
- Passo 6: Alterar a pagina Home para listar e excluir os contatos.
Passo 1: Criar o aplicativo
ionic start NOME_DO_APP blank
Passo 2: Instalar o Ionic Storage
npm install --save @ionic/storage
Passo 3: Configurar o Ionic Storage
A configuração do Ionic Storage fica no arquivo app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule } from '@angular/core'; import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular'; import { SplashScreen } from '@ionic-native/splash-screen'; import { StatusBar } from '@ionic-native/status-bar'; import { MyApp } from './app.component'; import { HomePage } from '../pages/home/home'; import { IonicStorageModule } from '@ionic/storage'; import { DatePipe } from '@angular/common'; import { ContactProvider } from '../providers/contact/contact'; @NgModule({ declarations: [ MyApp, HomePage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp), IonicStorageModule.forRoot() ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage ], providers: [ StatusBar, SplashScreen, {provide: ErrorHandler, useClass: IonicErrorHandler}, DatePipe, ContactProvider ] }) export class AppModule {}
Passo 4: Criar o provider para fazer o CRUD
ionic g provider contact
Arquivo contact.ts
import { Injectable } from '@angular/core'; import 'rxjs/add/operator/map'; import { Storage } from '@ionic/storage'; import { DatePipe } from '@angular/common'; @Injectable() export class ContactProvider { constructor(private storage: Storage, private datepipe: DatePipe) { } public insert(contact: Contact) { let key = this.datepipe.transform(new Date(), "ddMMyyyyHHmmss"); return this.save(key, contact); } public update(key: string, contact: Contact) { return this.save(key, contact); } private save(key: string, contact: Contact) { return this.storage.set(key, contact); } public remove(key: string) { return this.storage.remove(key); } public getAll() { let contacts: ContactList[] = []; return this.storage.forEach((value: Contact, key: string, iterationNumber: Number) => { let contact = new ContactList(); contact.key = key; contact.contact = value; contacts.push(contact); }) .then(() => { return Promise.resolve(contacts); }) .catch((error) => { return Promise.reject(error); }); } } export class Contact { name: string; phone: number; birth: Date; active: boolean; } export class ContactList { key: string; contact: Contact; }
Passo 5: Criar a pagina de inclusão/alteração de contatos
ionic g page edit-contact
Arquivo edit-contact.ts
import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular'; import { ContactProvider, Contact } from '../../providers/contact/contact'; @IonicPage() @Component({ selector: 'page-edit-contact', templateUrl: 'edit-contact.html', }) export class EditContactPage { model: Contact; key: string; constructor(public navCtrl: NavController, public navParams: NavParams, private contactProvider: ContactProvider, private toast: ToastController) { if (this.navParams.data.contact && this.navParams.data.key) { this.model = this.navParams.data.contact; this.key = this.navParams.data.key; } else { this.model = new Contact(); } } save() { this.saveContact() .then(() => { this.toast.create({ message: 'Contato salvo.', duration: 3000, position: 'botton' }).present(); this.navCtrl.pop(); }) .catch(() => { this.toast.create({ message: 'Erro ao salvar o contato.', duration: 3000, position: 'botton' }).present(); }); } private saveContact() { if (this.key) { return this.contactProvider.update(this.key, this.model); } else { return this.contactProvider.insert(this.model); } } }
Arquivo edit-contact.html
<ion-header> <ion-navbar> <ion-title> Ionic Storage Example </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-item> <ion-label stacked>Nome</ion-label> <ion-input type="text" name="name" [(ngModel)]="model.name"></ion-input> </ion-item> <ion-item> <ion-label stacked>Telefone</ion-label> <ion-input type="tel" name="phone" [(ngModel)]="model.phone"></ion-input> </ion-item> <ion-item> <ion-label stacked>Nascimento</ion-label> <ion-datetime displayFormat="DD/MM/YYYY" name="birth" [(ngModel)]="model.birth"></ion-datetime> </ion-item> <ion-item> <ion-label>Ativo</ion-label> <ion-checkbox name="active" [(ngModel)]="model.active"></ion-checkbox> </ion-item> </ion-list> <button ion-button block (click)="save()">Salvar</button> </ion-content>
Passo 6: Alterar a pagina Home para listar e excluir os contatos
Arquivo home.ts
import { Component } from '@angular/core'; import { NavController, ToastController } from 'ionic-angular'; import { ContactProvider, Contact, ContactList } from '../../providers/contact/contact'; @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { contacts: ContactList[]; constructor(public navCtrl: NavController, private contactProvider: ContactProvider, private toast: ToastController) { } ionViewDidEnter() { this.contactProvider.getAll() .then((result) => { this.contacts = result; }); } addContact() { this.navCtrl.push('EditContactPage'); } editContact(item: ContactList) { this.navCtrl.push('EditContactPage', { key: item.key, contact: item.contact }); } removeContact(item: ContactList) { this.contactProvider.remove(item.key) .then(() => { // Removendo do array de items var index = this.contacts.indexOf(item); this.contacts.splice(index, 1); this.toast.create({ message: 'Contato removido.', duration: 3000, position: 'botton' }).present(); }) } }
Arquivo home.html
<ion-header> <ion-navbar> <ion-title> Ionic Storage Example </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-list> <ion-card *ngFor="let item of contacts" [ngClass]="{'item-inactive': !item.contact.active }"> <ion-card-header> <h1>{{ item.contact.name }}</h1> </ion-card-header> <ion-card-content> <p>{{ item.contact.phone }} - {{ item.contact.birth | date:'dd/MM/yyyy' }} </p> </ion-card-content> <ion-row text-center> <ion-col> <button ion-button icon-left clear small (click)="editContact(item);"> <ion-icon name="create"></ion-icon> <div>Editar</div> </button> </ion-col> <ion-col> <button ion-button icon-left clear small (click)="removeContact(item);"> <ion-icon name="trash"></ion-icon> <div>Excluir</div> </button> </ion-col> <ion-col> <a href="tel:{{ item.contact.phone }}" ion-button icon-left clear small> <ion-icon name="call"></ion-icon> <div>Ligar</div> </a> </ion-col> </ion-row> </ion-card> </ion-list> <ion-fab right bottom> <button ion-fab color="primary" (click)="addContact()"><ion-icon name="add"></ion-icon></button> </ion-fab> </ion-content>
Clique no botão abaixo para ver o código fonte gerado nessa aula
[button style=”btn-primary btn-lg” type=”link” target=”true” title=”Código fonte gerado na aula” link=”https://github.com/fabricadecodigo/IonicStorageExample” linkrel=””]
Referências
- Ionic Storage: http://ionicframework.com/docs/storage/
- Ionic Datetime: http://ionicframework.com/docs/api/components/datetime/DateTime/
Gostou desse artigo? Aproveite e curta e compartilhe para que mais pessoas possam também visualiza-lo!
Ainda ficou alguma dúvida ou tem alguma sugestão? Deixa aí nos comentários!
Boa tarde, Felipe
Sou eu novamente, estou com uma dúvida quanto a armazenamento de geolocalização ionic offline.
Tem alguma coisa que me recomenda?
Desde já agradeço parceiro
Fala Itamar, depende do que você quer armazenar e o que você vai fazer com a informação.
Mas você pode usar o Ionic Storage ou o próprio SQLite.
Valeu!
Boa noite! Porque se eu altero o nome do campo exemplo ( na classe export class Contact eu altero o nome da ‘name: string’ para ‘nome: string’ ou acrescento mais um objeto da este erro:
Uncaught( inpromise) navigation stack needs at least one root page?
Fala Usley, blz?
Essa alteração que você fez não bate com a mensagem de erro.
Essa mensagem de erro diz que está faltando a rootPage.
La no app.component tem uma variavel para definir qual é a pagina que deve ser aberta por padrão.
Da uma olhada lá.
Valeu
Olá professor,
Essa é uma opção para salvar realtime database do firebase? Tem como me explicar o caminho que tenho que salvar?
Obrigado.
Fala Murilo, blz?
Para salvar dados com o Firebase você pode ver esse vídeo: http://www.fabricadecodigo.com/crud-firebase-ionic/
Valeu!
Olá prof. Parabéns pelo tutorial. Tenho um pedido, pois tentei de várias formas e não consegui, podeira fazer um exemplo de salvar os dados de uma api no sqlite pra uso offline caso o usuário nao tenha conexao com internet?
Desculpe não fui claro…
Gostaria de deixar os dados disponíveis offline persistente no dispositivo.
Aguardo Obrigado por sua resposta.
Com a SDK do Firebase para web, que é a usada no Ionic, não funciona muito bem a parte offline.
O ideal nesse caso seria ter uma API rest e salvar os dados no SQLite.
Valeu!
Fala Matteus, blz?
Obrigado pela sugestão.
Valeu!