Nessa vídeo aula eu mostro como incluir, alterar, excluir e consultar dados no SQLite com Ionic.
O que é o SQLite
Segundo o próprio site do SQLite, O SQLite é um motor de banco de dados SQL autônomo, de alta confiabilidade, incorporado, completo e de domínio público. O SQLite é o mecanismo de banco de dados mais utilizado no mundo.
Criando uma aplicação de exemplo
No vídeo acima e mostro como criar um app para salvar produtos utilizando o SQLite.
O passo a passo abaixo é o mesmo mostrado no vídeo.
- Passo 1: Criar o aplicativo.
- Passo 2: Instalar o plugin do SQLite.
- Passo 3: Adicionar a plataforma Android/iOS.
- Passo 4: Configurar o aplicativo.
- Passo 5: Criar o provider para criação do banco de dados.
- Passo 6: Inicializar a criação do banco de dados quando o app startar.
- Passo 7: Criar o provider para o CRUD de produtos.
- Passo 8: Criar o provider para listar as categorias.
- Passo 9: Alterar a pagina Home para listar, excluir e pesquisar produtos.
- Passo 10: Criar a pagina de inclusão/alteração de produtos.
Passo 1: Criar o aplicativo
ionic start NOME_DO_APP blank
Passo 2: Instalar o plugin do SQLite
ionic cordova plugin add cordova-sqlite-storage npm install --save @ionic-native/sqlite
Passo 3: Adicionar a plataforma Android/iOS
ionic cordova platform add android
ionic cordova platform add ios
Passo 4: Configurar o aplicativo
Arquivo app.module.ts
import { BrowserModule } from '@angular/platform-browser'; import { ErrorHandler, NgModule, LOCALE_ID } 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 { SQLite } from '@ionic-native/sqlite' import { DatabaseProvider } from '../providers/database/database'; import { ProductProvider } from '../providers/product/product'; import { CategoryProvider } from '../providers/category/category'; @NgModule({ declarations: [ MyApp, HomePage ], imports: [ BrowserModule, IonicModule.forRoot(MyApp) ], bootstrap: [IonicApp], entryComponents: [ MyApp, HomePage ], providers: [ StatusBar, SplashScreen, // Grande sacada para formatar numeros e datas no formato brasileiro {provide: LOCALE_ID, useValue: 'pt-BR'}, {provide: ErrorHandler, useClass: IonicErrorHandler}, SQLite, DatabaseProvider, ProductProvider, CategoryProvider ] }) export class AppModule {}
Passo 5: Criar o provider para criação do banco de dados
ionic g provider database
Arquivo database.ts
import { Injectable } from '@angular/core'; import { SQLite, SQLiteObject } from '@ionic-native/sqlite'; @Injectable() export class DatabaseProvider { constructor(private sqlite: SQLite) { } /** * Cria um banco caso não exista ou pega um banco existente com o nome no parametro */ public getDB() { return this.sqlite.create({ name: 'products.db', location: 'default' }); } /** * Cria a estrutura inicial do banco de dados */ public createDatabase() { return this.getDB() .then((db: SQLiteObject) => { // Criando as tabelas this.createTables(db); // Inserindo dados padrão this.insertDefaultItems(db); }) .catch(e => console.log(e)); } /** * Criando as tabelas no banco de dados * @param db */ private createTables(db: SQLiteObject) { // Criando as tabelas db.sqlBatch([ ['CREATE TABLE IF NOT EXISTS categories (id integer primary key AUTOINCREMENT NOT NULL, name TEXT)'], ['CREATE TABLE IF NOT EXISTS products (id integer primary key AUTOINCREMENT NOT NULL, name TEXT, price REAL, duedate DATE, active integer, category_id integer, FOREIGN KEY(category_id) REFERENCES categories(id))'] ]) .then(() => console.log('Tabelas criadas')) .catch(e => console.error('Erro ao criar as tabelas', e)); } /** * Incluindo os dados padrões * @param db */ private insertDefaultItems(db: SQLiteObject) { db.executeSql('select COUNT(id) as qtd from categories', {}) .then((data: any) => { //Se não existe nenhum registro if (data.rows.item(0).qtd == 0) { // Criando as tabelas db.sqlBatch([ ['insert into categories (name) values (?)', ['Hambúrgueres']], ['insert into categories (name) values (?)', ['Bebidas']], ['insert into categories (name) values (?)', ['Sobremesas']] ]) .then(() => console.log('Dados padrões incluídos')) .catch(e => console.error('Erro ao incluir dados padrões', e)); } }) .catch(e => console.error('Erro ao consultar a qtd de categorias', e)); } }
Passo 6: Inicializar a criação do banco de dados quando o app startar
Arquivo app.component.ts
import { Component } from '@angular/core'; import { Platform } from 'ionic-angular'; import { StatusBar } from '@ionic-native/status-bar'; import { SplashScreen } from '@ionic-native/splash-screen'; import { HomePage } from '../pages/home/home'; import { DatabaseProvider } from '../providers/database/database' @Component({ templateUrl: 'app.html' }) export class MyApp { rootPage: any = null; constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, dbProvider: DatabaseProvider) { platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. statusBar.styleDefault(); //Criando o banco de dados dbProvider.createDatabase() .then(() => { // fechando a SplashScreen somente quando o banco for criado this.openHomePage(splashScreen); }) .catch(() => { // ou se houver erro na criação do banco this.openHomePage(splashScreen); }); }); } private openHomePage(splashScreen: SplashScreen) { splashScreen.hide(); this.rootPage = HomePage; } }
Passo 7: Criar o provider para o CRUD de produtos
Arquivo product.ts
import { Injectable } from '@angular/core'; import { SQLiteObject } from '@ionic-native/sqlite'; import { DatabaseProvider } from '../database/database'; @Injectable() export class ProductProvider { constructor(private dbProvider: DatabaseProvider) { } public insert(product: Product) { return this.dbProvider.getDB() .then((db: SQLiteObject) => { let sql = 'insert into products (name, price, duedate, active, category_id) values (?, ?, ?, ?, ?)'; let data = [product.name, product.price, product.duedate, product.active ? 1 : 0, product.category_id]; return db.executeSql(sql, data) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } public update(product: Product) { return this.dbProvider.getDB() .then((db: SQLiteObject) => { let sql = 'update products set name = ?, price = ?, duedate = ?, active = ?, category_id = ? where id = ?'; let data = [product.name, product.price, product.duedate, product.active ? 1 : 0, product.category_id, product.id]; return db.executeSql(sql, data) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } public remove(id: number) { return this.dbProvider.getDB() .then((db: SQLiteObject) => { let sql = 'delete from products where id = ?'; let data = [id]; return db.executeSql(sql, data) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } public get(id: number) { return this.dbProvider.getDB() .then((db: SQLiteObject) => { let sql = 'select * from products where id = ?'; let data = [id]; return db.executeSql(sql, data) .then((data: any) => { if (data.rows.length > 0) { let item = data.rows.item(0); let product = new Product(); product.id = item.id; product.name = item.name; product.price = item.price; product.duedate = item.duedate; product.active = item.active; product.category_id = item.category_id; return product; } return null; }) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } public getAll(active: boolean, name: string = null) { return this.dbProvider.getDB() .then((db: SQLiteObject) => { let sql = 'SELECT p.*, c.name as category_name FROM products p inner join categories c on p.category_id = c.id where p.active = ?'; var data: any[] = [active ? 1 : 0]; // filtrando pelo nome if (name) { sql += ' and p.name like ?' data.push('%' + name + '%'); } return db.executeSql(sql, data) .then((data: any) => { if (data.rows.length > 0) { let products: any[] = []; for (var i = 0; i < data.rows.length; i++) { var product = data.rows.item(i); products.push(product); } return products; } else { return []; } }) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } } export class Product { id: number; name: string; price: number; duedate: Date; active: boolean; category_id: number; }
Passo 8: Criar o provider para listar as categorias
Arquivo category.ts
import { Injectable } from '@angular/core'; import { SQLiteObject } from '@ionic-native/sqlite'; import { DatabaseProvider } from '../database/database'; @Injectable() export class CategoryProvider { constructor(private dbProvider: DatabaseProvider) { } public getAll() { return this.dbProvider.getDB() .then((db: SQLiteObject) => { return db.executeSql('select * from categories', []) .then((data: any) => { if (data.rows.length > 0) { let categories: any[] = []; for (var i = 0; i < data.rows.length; i++) { var category = data.rows.item(i); categories.push(category); } return categories; } else { return []; } }) .catch((e) => console.error(e)); }) .catch((e) => console.error(e)); } }
Passo 9: Alterar a pagina Home para listar, excluir e pesquisar produtos
Arquivo home.ts
import { Component } from '@angular/core'; import { NavController, ToastController } from 'ionic-angular'; import { ProductProvider, Product } from '../../providers/product/product' @Component({ selector: 'page-home', templateUrl: 'home.html' }) export class HomePage { products: any[] = []; onlyInactives: boolean = false; searchText: string = null; constructor(public navCtrl: NavController, private toast: ToastController, private productProvider: ProductProvider) { } ionViewDidEnter() { this.getAllProducts(); } getAllProducts() { this.productProvider.getAll(!this.onlyInactives, this.searchText) .then((result: any[]) => { this.products = result; }); } addProduct() { this.navCtrl.push('EditProductPage'); } editProduct(id: number) { this.navCtrl.push('EditProductPage', { id: id }); } removeProduct(product: Product) { this.productProvider.remove(product.id) .then(() => { // Removendo do array de produtos var index = this.products.indexOf(product); this.products.splice(index, 1); this.toast.create({ message: 'Produto removido.', duration: 3000, position: 'botton' }).present(); }) } filterProducts(ev: any) { this.getAllProducts(); } }
Arquivo home.html
<ion-header> <ion-navbar> <ion-title> Ionic SQLite Example </ion-title> </ion-navbar> </ion-header> <ion-content padding> <ion-searchbar (ionInput)="filterProducts($event)" [(ngModel)]="searchText"></ion-searchbar> <ion-list> <ion-item-sliding *ngFor="let product of products"> <button ion-item (click)="editProduct(product.id)"> <h1>{{ product.name }}</h1> <h2>{{ product.category_name }}</h2> <h2>{{ product.duedate | date:'dd/MM/yyyy' }}</h2> <h2 class="price">{{ product.price | currency:'BRL':true }}</h2> </button> <ion-item-options side="left"> <button ion-button color="danger" (click)="removeProduct(product)"> <ion-icon name="trash"></ion-icon> Excluir </button> </ion-item-options> </ion-item-sliding> </ion-list> <ion-fab right bottom> <button ion-fab color="light" (click)="addProduct()"><ion-icon name="add"></ion-icon></button> </ion-fab> </ion-content> <ion-footer> <ion-toolbar> <p>Total: {{ products.length }}</p> <ion-list> <ion-item no-lines> <ion-label>Listar inativos</ion-label> <ion-toggle name="listarInativos" [(ngModel)]="onlyInactives" (ionChange)="getAllProducts()"></ion-toggle> </ion-item> </ion-list> </ion-toolbar> </ion-footer>
Arquivo home.scss
.price { color: color($colors, secondary); }
Passo 10: Criar a pagina de inclusão/alteração de produtos
ionic g page edit-product
Arquivo edit-product.ts
import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams, ToastController } from 'ionic-angular'; import { ProductProvider, Product } from '../../providers/product/product' import { CategoryProvider } from '../../providers/category/category' @IonicPage() @Component({ selector: 'page-edit-product', templateUrl: 'edit-product.html', }) export class EditProductPage { model: Product; categories: any[]; constructor( public navCtrl: NavController, public navParams: NavParams, private toast: ToastController, private productProvider: ProductProvider, private categoryProvider: CategoryProvider) { this.model = new Product(); if (this.navParams.data.id) { this.productProvider.get(this.navParams.data.id) .then((result: any) => { this.model = result; }) } } /** * Runs when the page has loaded */ ionViewDidLoad() { this.categoryProvider.getAll() .then((result: any[]) => { this.categories = result; }) .catch(() => { this.toast.create({ message: 'Erro ao carregar as categorias.', duration: 3000, position: 'botton' }).present(); }); } save() { this.saveProduct() .then(() => { this.toast.create({ message: 'Produto salvo.', duration: 3000, position: 'botton' }).present(); this.navCtrl.pop(); }) .catch(() => { this.toast.create({ message: 'Erro ao salvar o produto.', duration: 3000, position: 'botton' }).present(); }); } private saveProduct() { if (this.model.id) { return this.productProvider.update(this.model); } else { return this.productProvider.insert(this.model); } } }
Arquivo edit-product.html
<ion-header> <ion-navbar> <ion-title> Ionic SQLite 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>Preço</ion-label> <ion-input type="number" name="price" [(ngModel)]="model.price"></ion-input> </ion-item> <ion-item> <ion-label stacked>Vencimento</ion-label> <ion-datetime displayFormat="DD/MM/YYYY" name="duedate" min="2017" max="2020-12-31" [(ngModel)]="model.duedate"></ion-datetime> </ion-item> <ion-item> <ion-label stacked>Categoria</ion-label> <ion-select name="category_id" [(ngModel)]="model.category_id"> <ion-option *ngFor="let category of categories" value="{{ category.id }}">{{ category.name}}</ion-option> </ion-select> </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>
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/IonicSQLiteExample” linkrel=””]
Referências
- SQLite: https://www.sqlite.org/
- Ionic SQLite Native: http://ionicframework.com/docs/native/sqlite/
- Ionic SearchBar: http://ionicframework.com/docs/components/#searchbar
- SQLite Online: https://sqliteonline.com/
- SQLite Admin: http://sqliteadmin.orbmu2k.de/
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!