Como criar um CRUD com Ionic 2 + Firebase

Adson Rocha
7 min readApr 6, 2017

--

Aprenda os fundamentos das quatro operações básicas utilizadas em bases de dados — criação, listagem, atualização e remoção (create, read, update, delete), usando o Firebase.

Crie um projeto Ionic 2. Se você não sabe como fazer isso: clique aqui. Crie um novo projeto no Firebase e copie o objeto de configuração dele. Se você não sabe como fazer isso, clique aqui.

Você vai precisar configurar seu projeto Ionic 2 para integrar com o Firebase. Veja como fazer isso nesse outro post: clique aqui.

Nesse tutorial, vamos usar um objeto “Carro”, com quatro atributos para ilustrar os conceitos básicos de inclusão de registros:

let carro = {
id: "..."
dono: "Adson Rocha",
modelo: "Fusca",
multa: false
}

Criando a página de cadastro/listagem

Vamos precisar de uma página para listar os registros já cadastrados e para incluir novos. Usaremos a mesma página para duas etapas do CRUD (create, read), depois outra com mais duas operações (edit, delete) para simplificar o tutorial; mas você pode criar um componente para cada uma dessas telas, se quiser.

Execute o comando de geração de página do CLI do Ionic (via Prompt de Comandos) na pasta do projeto para gerar o componente.

ionic g page listaCarro
Figura 1. Comando do Ionic CLI para criar uma nova página

Note que o comando foi executado dentro da pasta do projeto (tutorial-ionic).

Isso faz com que uma pasta lista-carro, com 3 arquivos, seja incluída na estrutura do seu projeto, dentro da pasta src/pages. Os arquivos são:

  1. lista-carro.html
  2. lista-carro.scss
  3. lista-carro.ts

Atualize os atributos declarations e entryComponents do decorador@NgModule no arquivo src/app/pp.module.ts para sua aplicação enxergar o novo componente.

...

@NgModule({
declarations: [
...
ListaCarroPage
],
...
entryComponents: [
...
ListaCarroPage
],
...
})
export class AppModule {}

Listando os registos já cadastrados

Passamos então para a implementação do componente. No arquivo lista-carro.ts vamos fazer a injeção do AngularFire2 e criar uma referência para a nossa base de dados no Firebase chamada carros . Note que a variável lista é do tipo FirebaseListObservable. Isso faz com que qualquer alteração na base de dados seja sincronizada automaticamente com essa variável.

...
import { FirebaseListObservable, AngularFire } from "angularfire2";

export class Carro{
id: string;
dono: string;
modelo: string;
multa: boolean
}

@Component({
...
})
export class ListaCarroPage {
lista: FirebaseListObservable<any>;
carro: Carro;

constructor(public af: AngularFire, ...) {
this.lista = this.af.database.list('/carros');
this.carro = new Carro();
}

cadastrar(){
...
}

editar(id){
...
}
}

No arquivo lista-carro.html vamos criar uma lista usando o componente ion-list do Ionic 2. Para cada registro na variável lista a diretiva *ngFor irá iterar para mostrar um item, nomeado como carro . Usando interpolação do Angular 2{{...}} mostramos os valores dos atributos de cada carro.

<ion-header>
<ion-navbar>
<ion-title>Lista de Carros</ion-title>
</ion-navbar>
</ion-header>

<ion-content>
<ion-list>
<ion-item *ngFor="let carro of lista | async">
<h2>{{carro.modelo}}</h2>
<h3>{{carro.dono}}</h3>
<ion-note item-right *ngIf="carro.multa === 'true'">
Tem multa
</ion-note>
</ion-item>
</ion-list>
</ion-content>

No trecho acima, usamos o “pipe” async para definir o tipo de sincronização que esperamos com a base de dados no Firebase. A diretiva *ngIf é usada para mostrar a nota “Tem multa” apenas quando o atributo multa do registro carro for verdadeiro.

Adicionando um novo registro

Precisamos de um formulário para cadastro de novos carros. Para simplificar, não vamos aqui nos preocupar com validação dos dados ou a melhor forma de vincular os campos de entrada de dados com o objeto que será salvo no banco de dados (tópico para outra postagem).

No componente ListaCarroPage, vamos criar uma variável carro para usarmos na inclusão de registros — você pode inclusive exportar uma classe auxiliar para dar tipo ao atributo, como no trecho abaixo:

...
export class Carro{
id: string;
dono: string;
modelo: string;
multa: boolean
}
@Component({
...
})
export class EditaCarroPage {
carro: Carro;
...
}

No método cadastrar, ainda no componente ListaCarroPage, vamos usar a lista vinculada com o Firebase para acessar o banco e incluir o novo registro. Na função de retorno dessa operação redefinimos a variável carro do componente para limpar os campos do formulário.

cadastrar(){
this.lista.push(this.carro).then(() => {
this.carro = new Carro();
});
}

No construtor do componente ListaCarroPage, inicializamos a variável carro para evitarmos erros no two-way-data-binding [(ngModel)]dos campos do formulário.

constructor(...) {
...
this.carro = new Carro();
}

No arquivo lista-carro.html , incluímos os campos para vincular com os atributos do carro:

<ion-content>
<ion-list>
<ion-item>
<ion-label fixed>Dono:</ion-label>
<ion-input type="text" [(ngModel)]="carro.dono"></ion-input>
</ion-item>
<ion-item>
<ion-label>Modelo</ion-label>
<ion-select [(ngModel)]="carro.modelo">
<ion-option value="Gol">Gol</ion-option>
<ion-option value="Fusca">Fusca</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Multa</ion-label>
<ion-select [(ngModel)]="carro.multa">
<ion-option value="false">Não</ion-option>
<ion-option value="true">Sim</ion-option>
</ion-select>
</ion-item>
<ion-item>
<button ion-button (click)="cadastrar()">Cadastrar</button>
</ion-item>
</ion-list>

<ion-list>
...
</ion-list>
</ion-content>

Primeiro teste

Navegue até a página lista-carro a partir da sua página inicial do aplicativo Ionic 2. Se você não sabe como fazer isso, clique aqui.

Ao preencher os campos clicar em “Cadastrar”, verifique na aba “Dados” do menu “Database” no console do Firebase, se o registro foi incluído:

Na sua página, a lista será atualizada:

Editando um registro

Para editar um registro, vamos precisar selecioná-lo na lista para então abrir uma outra página com os detalhes e o botão de atualização.

Crie um novo componente (página) para fazer a edição, da mesma forma que criamos a página de listagem anteriormente:

ionic g page editaCarro

Novamente, três arquivos (ts, scss e html) foram adicionados em um diretório src/pages/edita-carro na estrutura do seu projeto.

No arquivo edita-carro.ts vamos criar uma variável carro para representar o registro que está sendo editado.

...

@Component({
...
})
export class EditaCarroPage {
ref: FirebaseObjectObservable<any>;
id: string;
carro: Carro;
constructor(public navCtrl: NavController,
public navParams: NavParams,
public viewCtrl: ViewController,
public af: AngularFire) {

this.id = this.navParams.get('id');
this.ref = this.af.database.object('/carros/' + this.id);
}

salvar(){
this.ref.update(this.carro).then(() => {
this.viewCtrl.dismiss();
});
}
fechar(){
this.viewCtrl.dismiss();
}
}

É importante destacar aqui, que precisamos do id do registro a ser atualizado nessa página. Por isso usamos o NavParams do Ionic 2 para acessá-lo no construtor:

this.id = this.navParams.get('id');

O método salvar utiliza uma referência para o registro (objeto) no banco de dados Firebase (/carros/id).

this.ref.update(this.carro).then(...);

O comando this.viewCtrl.dismiss() , chamado depois de se atualizar o objeto ou no método fechar , apenas fecha o modal de edição.

Vinculando o clique no item da listagem com a edição do registro

Na página de listagem de carros, ao se clicar em um item, vamos chamar uma nova janela na forma de modal e passar o id do carro como parâmetro. Para isso, injete o serviço ModalController no construtor do componente ListaCarroPage.

constructor(..., public modal: ModalController) {
...
}

Depois, crie um método editarnesse mesmo componente:

editar(id){
this.modal.create(EditaCarroPage, {id: id}).present();
}

Lembre-se que você vai precisar importar o componente EditaCarroPage em ListaCarroPage e registrar EditaCarroPage no decorador @NgModel do arquivo app.module.ts .

Agora, no arquivo lista-carro.html , altere a linha que cria os elementos ion-item para que eles respondam ao evento de click, passando o id do carro selecionado como parâmetro para o método editar .

<ion-list>
<ion-item *ngFor="..." (click)="editar(carro.$key)">
...
</ion-item>
</ion-list>

O marcador $key recupera o id do registro gravado no banco de dados do Firebase.

No arquivo edita-carro.html temos o formulário com os campos para a edição:

<ion-header>
<ion-toolbar>
<ion-title>Edição</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="fechar()">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list>
<ion-item>
<ion-label fixed>Dono:</ion-label>
<ion-input type="text" [(ngModel)]="carro.dono"></ion-input>
</ion-item>
<ion-item>
<ion-label>Modelo</ion-label>
<ion-select [(ngModel)]="carro.modelo">
<ion-option value="Gol">Gol</ion-option>
<ion-option value="Fusca">Fusca</ion-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Multa</ion-label>
<ion-select [(ngModel)]="carro.multa">
<ion-option value="false">Não</ion-option>
<ion-option value="true">Sim</ion-option>
</ion-select>
</ion-item>
<ion-item>
<button ion-button (click)="salvar()">Salvar</button>
</ion-item>
</ion-list>
</ion-content>

Faça o teste, clicando sobre um dos carros da lista e cliquem em “Salvar”.

Falta agora apenas a exclusão para completarmos o nosso exemplo de CRUD com Firebase!

Vamos alterar o componente EditaCarroPage, criando um novo método: excluir .

@Component({
...
})
export class EditaCarroPage {
ref: FirebaseObjectObservable<any>;
...
constructor(...) {
...
}
excluir(id){
this.ref.remove();
this.viewCtrl.dismiss();
}
}

Como a variável this.ref guarda uma referência para o objeto no banco de dados, só precisamos chamar o método remove() do AngularFire2.

No arquivo edita-carro.html vamos criar um botão para chamar a função excluir.

<ion-header>
...
</ion-header>
<ion-content>
<ion-list>
...
<ion-item>
<button ion-button ...>Salvar</button>
<button ion-button (click)="excluir(carro.$key)">
Excluir
</button>
</ion-item>
</ion-list>
</ion-content>

Pronto, você já tem um CRUD completo usando o Ionic 2 e Firebase. Há várias melhorias que podem ser feitas nesse código, como o uso do FormBuilder para validação dos dados, uso de Alert-Confirm antes de se excluir um registro, o uso do Loading ao carregar a lista, entre outros. Deixamos para as próximas postagens.

Se gostou do tutorial, curta e compartilhe!

--

--

Adson Rocha

Ph.D. in Computer Engineering and professor at Goiano Federal Institute (Brazil).