Nessa vídeo aula eu mostro como criar um CRUD (CRUD significa, em inglês, Create, Read, Update e Delete e em português é Incluir, Alterar, Excluir e Consultar) com Angular e Firebase Realtime Database.
O que é o Firebase Realtime Database
O Firebase Realtime Database é um banco de dados NoSQL hospedado na nuvem. Com ele, você armazena e sincroniza dados entre os seus usuários em tempo real.
Para saber mais você pode acessar diretamente a página do Firebase clicando aqui.
Pré requisitos
Ter um projeto já criado no console do Firebase e com as permissões de leitura e escrita habilitadas. (Isso é mostrado no vídeo)
Esse tutorial está utilizando as seguintes versões das dependências:
- Angular: 7.0
- Firebase: 5.5.5
- AngularFire2: 5.1.0
Passo a passo para o CRUD
- Instalar o Firebase no projeto
- Criar os componentes, services e classes
- Criar a classe que vai ter os dados do contato
- Criar o service que vai compartilhar o contato entre os dois componentes
- Criar o service que fará o CRUD
- Criar o formulário de cadastro
- Criar a lista de contatos
1 – Instalar o Firebase no projeto
Para fazer a integração do Firebase com o Angular é necessário usar uma biblioteca desenvolvida pelo próprio time do Angular que se chama AngularFire2.
Para instalar, basta rodar o comando abaixo que vai instalar a exata versão do Firebase e AngularFire2 usada nesse tutorial
npm install [email protected] @angular/[email protected] --save
Próximo passo é adicionar as configurações do Firebase no arquivo environment.ts. Essas configurações podem ser obtidas na página do projeto.
firebase: {
apiKey: "[SUA KEY]",
authDomain: "[SEU AUTH DOMAIN]",
databaseURL: "[SUA DATABASE URL]",
projectId: "[SEU PROJECT ID]",
storageBucket: "[SEU STORAGE BUCKET]",
messagingSenderId: "[SUA MESSAGING SENDER ID]"
}
Feito isso, agora é necessário importar no app.module os módulos do AngularFire2 que serão usados. Nesse tutorial será usado apenas o modulo do Firebase Realtime Database.
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire';
import { AngularFireDatabaseModule } from '@angular/fire/database';
import { environment } from '../environments/environment';
import { EditComponent } from './contatos/edit/edit.component';
import { ListComponent } from './contatos/list/list.component';
@NgModule({
declarations: [
AppComponent,
EditComponent,
ListComponent
],
imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFireDatabaseModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2 – Criar os componentes, services e classes
O projeto será um CRUD de contatos com nome e telefone, para isso é necessário criar um componente para o formulário e outro para a lista de contatos. Alem disso será criado o service que fará o crud no Firebase.
Basta rodar os comandos abaixo para a criação dos componentes, services e classes.
ng g component contatos/edit ng g component contatos/list ng g service contatos/shared/contato ng g service contatos/shared/contato-data ng g class contatos/shared/contato
3 – Classe com os dados do contato
O arquivo contato.ts deve ficar com o conteúdo abaixo.
export class Contato {
nome: string = '';
telefone: string = '';
}
4 – Service para compartilhar o contato entre os componentes
Durante a alteração de um contato, é necessário enviar o contato que está sendo editado para o componente de formulário.
Para isso o o arquivo contato-data.service.ts deve ficar com o conteúdo abaixo.
Como o foco do tutorial é mostrar o CRUD, esse arquivo não será explicado aqui mas ele é explicado no vídeo.
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { Contato } from './contato';
@Injectable({
providedIn: 'root'
})
export class ContatoDataService {
private contatoSource = new BehaviorSubject({ contato: null, key: '' });
currentContato = this.contatoSource.asObservable();
constructor() { }
changeContato(contato: Contato, key: string) {
this.contatoSource.next({ contato: contato, key: key });
}
}
5 – Service responsável pelo CRUD.
O service tem 4 métodos: Inclusão, alteração, consulta e exclusão.
Para incluir um dado no Firebase é necessário acessar o nó onde os dados serão salvos e executar o método push passando como parâmetro o dado que deve ser incluído, conforme abaixo.
Método para incluir um registro
insert(contato: Contato) {
this.db.list('contato').push(contato)
.then((result: any) => {
console.log(result.key);
});
}
Para alterar um dado no Firebase, é necessário acessar o nó onde os dados serão salvos e executar o método update passando como parâmetro a key do objeto e o dados que deve ser alterado, conforme abaixo.
update(contato: Contato, key: string) {
this.db.list('contato').update(key, contato)
.catch((error: any) => {
console.error(error);
});
}
Para buscar uma lista de dados no Firebase, é necessário acessar o nó onde os dados estão e mapear da maneira que você quer acessar as propriedades desse objeto para mostrar na tela, conforme abaixo.
getAll() {
return this.db.list('contato')
.snapshotChanges()
.pipe(
map(changes => {
return changes.map(c => ({ key: c.payload.key, ...c.payload.val() }));
})
);
}
E por fim, para excluir, basta acessar o nó do objeto e executar o método remove, conforme abaixo.
delete(key: string) {
this.db.object(`contato/${key}`).remove();
}
O arquivo contato.service.ts com todos os métodos explicados acima deve ficar conforme abaixo.
import { Injectable } from '@angular/core';
import { AngularFireDatabase } from '@angular/fire/database';
import { Contato } from './contato';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ContatoService {
constructor(private db: AngularFireDatabase) { }
insert(contato: Contato) {
this.db.list('contato').push(contato)
.then((result: any) => {
console.log(result.key);
});
}
update(contato: Contato, key: string) {
this.db.list('contato').update(key, contato)
.catch((error: any) => {
console.error(error);
});
}
getAll() {
return this.db.list('contato')
.snapshotChanges()
.pipe(
map(changes => {
return changes.map(c => ({ key: c.payload.key, ...c.payload.val() }));
})
);
}
delete(key: string) {
this.db.object(`contato/${key}`).remove();
}
}
6 – Formulário de cadastro
Para salvar os contatos no Firebase o formulário criado nesse tutorial fica conforme abaixo
edit.component.ts
import { Component, OnInit, Input } from '@angular/core';
import { Contato } from '../shared/contato';
import { ContatoService } from '../shared/contato.service';
import { ContatoDataService } from '../shared/contato-data.service';
@Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.scss']
})
export class EditComponent implements OnInit {
contato: Contato
key: string = '';
constructor(private contatoService: ContatoService, private contatoDataService: ContatoDataService) { }
ngOnInit() {
this.contato = new Contato();
this.contatoDataService.currentContato.subscribe(data => {
if (data.contato && data.key) {
this.contato = new Contato();
this.contato.nome = data.contato.nome;
this.contato.telefone = data.contato.telefone;
this.key = data.key;
}
})
}
onSubmit() {
if (this.key) {
this.contatoService.update(this.contato, this.key);
} else {
this.contatoService.insert(this.contato);
}
this.contato = new Contato();
}
}
edit.component.html
<form (ngSubmit)="onSubmit()">
<div class="form-group">
<label>Nome</label>
<input type="text" class="form-control" [(ngModel)]="contato.nome" name="nome" />
</div>
<div class="form-group">
<label>Telefone</label>
<input type="tel" class="form-control" [(ngModel)]="contato.telefone" name="telefone" />
</div>
<button type="submit" class="btn btn-primary">Salvar</button>
</form>
7 – Listagem de contato
Para exibir os contatos cadastrados na tela, o componente criado nesse tutorial fica conforme abaixo.
list.component.ts
import { Contato } from './../shared/contato';
import { Component, OnInit } from '@angular/core';
import { ContatoService } from '../shared/contato.service';
import { Observable } from 'rxjs';
import { ContatoDataService } from '../shared/contato-data.service';
@Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.scss']
})
export class ListComponent implements OnInit {
contatos: Observable<any>;
constructor(private contatoService: ContatoService, private contatoDataService: ContatoDataService) { }
ngOnInit() {
this.contatos = this.contatoService.getAll();
}
delete(key: string) {
this.contatoService.delete(key);
}
edit(contato: Contato, key: string) {
this.contatoDataService.changeContato(contato, key);
}
}
list.component.html
<div class="card mt-2" *ngFor="let contato of contatos | async">
<div class="card-body">
<h5 class="card-title">{{contato.nome}}</h5>
<p class="card-text">{{contato.telefone}}</p>
</div>
<div class="card-footer">
<button type="button" class="btn btn-default" (click)="edit(contato, contato.key)">Editar</button>
<button type="button" class="btn btn-danger ml-2" (click)="delete(contato.key)">Excluir</button>
</div>
</div>
Referencias
- Firebase: https://firebase.google.com/
- AngularFire2: https://github.com/angular/angularfire2