Construindo uma aplicação Ionic CRUD com Firestore

O Firestore é o novo banco de dados do Firebase. É um banco de dados orientado a documentos NoSQL para desenvolvimento móvel e web.

Ele é projetado para armazenar e sincronizar dados de aplicativos em escala global com facilidade. Algumas de suas principais características incluem:

  • Documentos e Coleções com consultas poderosas.
  • Acesso off-line ao WEB SDK.
  • Sincronização de dados em tempo real.

Hoje vamos aprender a integrar o Firestore com o Ionic para criar um fluxo de trabalho CRUD. Este aplicativo de amostra mostrará a você como:

  • Mostrando uma lista de itens do seu banco de dados ( que no Firestore é chamado exibindo uma coleção de documentos ).
  • Criando um novo item e adicionando-o à lista.
  • Navegar para a página de detalhes desse item.
  • Excluindo um item da nossa lista.

captura de tela mostrando as diferentes visualizações para o firestore CRUD

Vamos dividir este processo em X passos:

  • Etapa 1: crie e inicialize nosso aplicativo Ionic.
  • Etapa 2: adicione itens à lista.
  • Passo # 3: Mostre a lista de itens.
  • Passo # 4: Navegue até a página de detalhes de um item.
  • Etapa 5: excluir um item da lista.

Agora que sabemos o que vamos fazer, vamos pular para o modo de codificação.

Etapa 1: criar e inicializar seu aplicativo

O objetivo desta etapa é criar seu novo aplicativo iônico, instalar os pacotes necessários ( somente Firebase e AngularFire2 ) e inicializar nosso aplicativo do Firebase.

Com isso em mente, vamos criar nosso aplicativo primeiro, abrir seu terminal e navegar até a pasta que você usa para codificação ( ou em qualquer lugar que você quiser, para mim, essa é a pasta Desenvolvimento ) e criar seu aplicativo:

cd Development/
ionic start firestore-example blank
cd firestore-example 

Depois que criarmos o aplicativo, precisaremos instalar o Firebase. Para isso, abra o terminal novamente e ( enquanto estiver na raiz do projeto ), digite:

npm install angularfire2 firebase

Esse comando instalará as versões estáveis ​​mais recentes do AngularFire2 e do Firebase Web SDK.

Agora que instalamos tudo, vamos conectar o Ionic ao nosso aplicativo do Firebase.

A primeira coisa que precisamos é obter as credenciais do nosso aplicativo, fazer login no Firebase Console e navegar até o aplicativo do Firebase ( ou criar um novo caso você ainda não tenha o aplicativo ).

Na guia Visão geral do projeto, você verá a tela “Primeiros passos”, com opções para adicionar o Firebase a diferentes tipos de aplicativos, e selecione “Adicionar o Firebase ao seu aplicativo da web”.

De todo o código que aparece nessa janela pop-up, concentre-se nesse bit:

var config = {
  apiKey: "Your credentials here",
  authDomain: "Your credentials here",
  databaseURL: "Your credentials here",
  projectId: "Your credentials here",
  storageBucket: "Your credentials here",
  messagingSenderId: "Your credentials here",
};

Esse é o seu objeto de configuração do Firebase, ele tem todas as informações necessárias para acessar as diferentes APIs do Firebase, e precisaremos disso para conectar nosso aplicativo iônico ao nosso aplicativo do Firebase.

Vá para a sua src/apppasta e crie um arquivo chamado credentials.tsa idéia deste arquivo é manter todas as nossas credenciais em um só lugar, este arquivo não deve estar no controle de origem para adicioná-lo ao seu .gitignorearquivo.

Copie seu objeto de configuração para essa página. Vou mudar o nome para algo que faça mais sentido para mim:

export var firebasConfig = {
  apiKey: "AIzaSyBJT6tfre8uh3LGBm5CTiO5DUZ4",
  authDomain: "javebratt-playground.firebaseapp.com",
  databaseURL: "https://javebratt-playground.firebaseio.com",
  projectId: "javebratt-playground",
  storageBucket: "javebratt-playground.appspot.com",
  messagingSenderId: "3676553551"
};

Estamos exportando para que possamos importá-lo para outros arquivos onde precisarmos.

Agora é hora da parte final desta etapa, precisamos inicializar o Firebase, para isso, vamos entrar app.module.tse, primeiro, vamos importar os pacotes AngularFire2 que precisaremos e nosso objeto de credencial:

import { AngularFireModule } from 'angularfire2';
import { AngularFirestoreModule } from 'angularfire2/firestore';
import { firebaseConfig } from './credentials';

Como vamos usar apenas o banco de dados Firestore, importamos o módulo de base AF2 ( vou me referir a AngularFire2 como AF2 de agora em diante ) e o módulo Firestore. Se você também precisasse de autenticação ou armazenamento, você precisaria adicionar esses módulos aqui.

Dentro de sua @NgModule()aparência para sua importsmatriz e adicione o módulo AF2 e o módulo Firestore:

imports: [
  BrowserModule,
  IonicModule.forRoot(MyApp),
  AngularFireModule.initializeApp(firebaseConfig),
  AngularFirestoreModule,
],

Estamos chamando o .initializeApp(firebaseConfig)método e passando nosso objeto de credencial para que nosso aplicativo saiba como se conectar ao Firebase.

E é isso, pode não parecer muito ainda , mas nossos aplicativos Firebase e Ionic agora podem conversar entre si.

Etapa 2: adicione itens à lista.

É hora de começar a trabalhar com nossos dados, vamos construir um aplicativo CRUD, usaremos uma lista de músicas como um exemplo, mas os mesmos princípios se aplicam a qualquer fluxo de trabalho Mestre / Detalhe que você queira construir.

A primeira coisa que precisamos é entender como nossos dados são armazenados, o Firestore é um banco de dados NoSQL orientado a documentos, que é um pouco diferente do RTDB ( banco de dados em tempo real ).

Isso significa que temos dois tipos de dados em nosso banco de dados, documentos, que são objetos com os quais podemos trabalhar, e coleções que são os contêineres que agrupam esses objetos.

Por exemplo, se estivermos criando um banco de dados de músicas, nossa coleção seria chamada songs, ou songList, que conteria todos os objetos de música individuais e cada objeto teria suas propriedades, como o nome da música, o artista etc.

Em nosso exemplo, o objeto song terá cinco propriedades, um id, o álbum, o artista, uma descrição e o nome da música. No espírito de aproveitar os recursos de verificação de tipos do TypeScript, vamos criar uma interface que funcione como modelo para todas as nossas músicas.

Vá até a srcpasta e crie uma pasta chamada models, adicione um arquivo chamado song.interface.tse preencha-o com os seguintes dados:

export interface Song {
  id: string;
  albumName: string;
  artistName: string;
  songDescription: string;
  sonName: string;
}

Essa é a interface da música e garante que, sempre que estivermos trabalhando com um objeto de música, ele tenha todos os dados necessários.

Para começar a criar novas músicas e adicioná-las à nossa lista, precisamos ter uma página que contenha um formulário para inserir os dados da música, criar essa página com o Ionic CLI, abrir o terminal e digitar:

ionic generate page Create

Na verdade, enquanto estamos nisso, vamos dedicar alguns minutos para criar a página de detalhes, uma visualização detalhada de uma música específica e o provedor de Firestore, ele cuidará de todas as interações do banco de dados para que possamos gerenciar tudo desse arquivo.

ionic generate page Detail
ionic generate provider Firestore

Agora precisamos de uma maneira de ir da home page para o CreatePage, para que abrir home.htmle alterar seu cabeçalho para ficar assim:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Song List
    </ion-title>
    <ion-buttons end>
      <button ion-button icon-only (click)="goToCreatePage()">
        <ion-icon name="add"></ion-icon>
      </button>
    </ion-buttons>
  </ion-navbar>
</ion-header>

Estamos adicionando um botão ao cabeçalho que aciona a goToCreatePage()função, para que funcione, vamos abrir o home.tsarquivo e escrever essa função:

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
})
export class HomePage {
  constructor(public navCtrl: NavController) {}

  goToCreatePage(): void {
    this.navCtrl.push('CreatePage');
  }
}

A única coisa que esta função está fazendo é levá-lo para o CreatePage, agora que podemos chegar a essa página, é hora de construir sua funcionalidade. A funcionalidade consistirá em 3 coisas:

  • A exibição de HTML que mostra o formulário.
  • A classe TypeScript que coleta os dados do formulário e os envia ao provedor.
  • A função no provedor que cria a música e a adiciona à lista de músicas.

Vamos começar com o HTML, abrir o create.htmlarquivo e dentro das <ion-content></ion-content>tags criar o formulário:

<ion-content>
  <form [formGroup]="createSongForm" (submit)="createSong()" novalidate>
    <ion-item>
      <ion-label stacked>Song Name</ion-label>
      <ion-input formControlName="songName" type="text" 
        placeholder="What's this song called?">
      </ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Artist Name</ion-label>
      <ion-input formControlName="artistName" type="text" 
        placeholder="Who sings this song?">
      </ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Album Name</ion-label>
      <ion-input formControlName="albumName" type="text" 
        placeholder="What's the album's name?">
      </ion-input>
    </ion-item>

    <ion-item>
      <ion-label stacked>Song Description</ion-label>
      <ion-textarea formControlName="songDescription" type="text" 
        placeholder="What's this song about?">
      </ion-textarea>
    </ion-item>


    <button ion-button block type="submit" [disabled]="!createSongForm.valid">
      Add Song
    </button>
  </form>

</ion-content>

Se você é novo em formas angulares, então aqui está o que está acontecendo:

  • [formGroup]="createSongForm" => Este é o nome do formulário que estamos criando.
  • (submit)="createSong()"=> Isso indica o formulário que, ao enviar, deve chamar a createSong()função.
  • formControlName => Este é o nome do campo.
  • [disabled]="!createSongForm.valid" => Isso define o botão a ser desativado até que o formulário seja válido.

Agora vamos para o create.tsarquivo, aqui coletamos os dados do nosso formulário e passamos para o nosso provedor. Primeiro, vamos importar tudo o que precisaremos:

import { Component } from '@angular/core';
import {
  IonicPage,
  NavController,
  Loading,
  LoadingController,
  AlertController,
  Alert,
} from 'ionic-angular';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { FirestoreProvider } from '../../providers/firestore/firestore';

Estamos importando:

  • Formulário métodos auxiliares de @angular/forms.
  • Carregando controlador para mostrar um widget de carregamento para nossos usuários enquanto o formulário processa os dados.
  • Alertar o controlador para exibir um alerta para o nosso usuário, se houver algum erro.
  • E o provedor Firestore para chamar a função que adicionará a música ao banco de dados.

Agora precisamos injetar todos esses provedores no construtor e inicializar nosso formulário:

public createSongForm: FormGroup; // This is the form we're creating.

constructor(
  public navCtrl: NavController,
  public loadingCtrl: LoadingController,
  public alertCtrl: AlertController,
  public firestoreProvider: FirestoreProvider,
  formBuilder: FormBuilder
) {
  this.createSongForm = formBuilder.group({
    albumName: ['', Validators.required],
    artistName: ['', Validators.required],
    songDescription: ['', Validators.required],
    songName: ['', Validators.required],
  });
}

E agora tudo que precisamos é a função que coleta os dados e os envia para o provedor, se você se lembrar da parte HTML, nós a chamamos createSong()

createSong(): void { }

A primeira coisa que queremos fazer dentro dessa função é acionar um componente de carregamento que permitirá ao usuário saber que os dados estão sendo processados ​​e, depois disso, extrairemos todos os dados de campo do formulário.

createSong(): void {
  const loading: Loading = this.loadingCtrl.create();
  loading.present();

  const albumName = this.createSongForm.value.albumName;
  const artistName = this.createSongForm.value.artistName;
  const songDescription = this.createSongForm.value.songDescription;
  const songName = this.createSongForm.value.songName;
}

E, por último, enviaremos os dados para o provedor, assim que a música for criada com sucesso, o usuário deverá navegar de volta para a página anterior, e se houver algo errado ao criá-lo, exibiremos um alerta com a mensagem de erro.

createSong(): void {
  const loading: Loading = this.loadingCtrl.create();
  loading.present();

  const albumName = this.createSongForm.value.albumName;
  const artistName = this.createSongForm.value.artistName;
  const songDescription = this.createSongForm.value.songDescription;
  const songName = this.createSongForm.value.songName;

  this.firestoreProvider
    .createSong(albumName, artistName, songDescription, songName)
    .then(
      () => {
        loading.dismiss().then(() => {
          this.navCtrl.pop();
        });
      },
      error => {
        loading.dismiss().then(() => {
          const alert: Alert = this.alertCtrl.create({
            message: error.message,
            buttons: [{ text: 'Ok', role: 'cancel' }],
          });
          alert.present();
        });
      }
    );
}

OBSERVAÇÃO: Como uma boa prática, manipule esses erros você mesmo, em vez de mostrar a mensagem de erro padrão para os usuários, certifique-se de fazer algo mais fácil de usar e usar suas mensagens personalizadas, somos técnicos, sabemos o que o erro significa, do tempo que nossos usuários não vão.

Nós quase terminamos essa parte, tudo que precisamos agora é criar a função dentro do provedor que recebe todos os dados do formulário que estamos enviando e usa para criar uma música em nosso banco de dados.

Abra providers/firestore/firestore.tse vamos fazer algumas coisas, precisamos:

  • Importar Firestore.
  • Importe nossa interface de música.
  • Injetar firestore no construtor.
  • E escreva a createSong()função que leva todos os parâmetros que enviamos do nosso formulário.
import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Song } from '../../models/song.interface';

@Injectable()
export class FirestoreProvider {
  constructor(public firestore: AngularFirestore) {}

  createSong(
    albumName: string,
    artistName: string,
    songDescription: string,
    songName: string
  ): Promise<void> { }
}

A função está tomando todos os parâmetros que estamos enviando. Agora vamos fazer algo que possa parecer incomum . Nós vamos usar a createId()função firestore para gerar um id para a nossa nova música.

import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Song } from '../../models/song.interface';

@Injectable()
export class FirestoreProvider {
  constructor(public firestore: AngularFirestore) {}

  createSong(
    albumName: string,
    artistName: string,
    songDescription: string,
    songName: string
  ): Promise<void> {
    const id = this.firestore.createId();
  }
}

O Firestore gera automaticamente IDs para nós quando enviamos itens para uma lista, mas eu gosto de criar primeiro o ID e depois armazená-lo dentro do item. Dessa forma, se eu puxar um item, posso obter sua ID e não tem que fazer quaisquer outras operações para obtê-lo.

Agora que criamos o id, vamos criar uma referência para essa música e definir todas as propriedades que temos, incluindo o id.

import { Injectable } from '@angular/core';
import { AngularFirestore } from 'angularfire2/firestore';
import { Song } from '../../models/song.interface';

@Injectable()
export class FirestoreProvider {
  constructor(public firestore: AngularFirestore) {}

  createSong(
    albumName: string,
    artistName: string,
    songDescription: string,
    songName: string
  ): Promise<void> {
    const id = this.firestore.createId();

    return this.firestore.doc(`songList/${id}`).set({
      id,
      albumName,
      artistName,
      songDescription,
      songName,
    });
  }
}

Essa última parte do código está criando uma referência ao documento identificado com esse ID em nossa songListcoleção e, depois de criar a referência, ele adiciona todas as informações que enviamos como parâmetros.

E é isso. Agora você pode adicionar músicas à nossa lista. E uma vez que cada música é criada, o usuário irá navegar de volta para a página inicial, onde vamos mostrar a lista de músicas armazenadas no banco de dados.

Passo # 3: Mostre a lista de itens.

Para mostrar a lista de músicas, seguiremos a mesma abordagem que usamos para nossa última funcionalidade, criaremos a exibição HTML, a classe TypeScript e a função dentro do provedor que se comunica com o Firebase.

Já que temos o provedor aberto a partir da funcionalidade anterior vamos começar por aí, queremos criar uma função chamada de getSongList()função que deva retornar uma coleção de músicas:

getSongList(): AngularFirestoreCollection<Song> {
  return this.firestore.collection(`songList`);
}

Note que para isso funcionar você precisa importar AngularFirestoreCollectiondo angularfire2/firestorepacote ( ou remover a verificação de tipo se você não se importa com isso ).

Agora, vamos para a página inicial e importamos tudo o que precisaremos:

import { Song } from '../../models/song.interface';
import { FirestoreProvider } from '../../providers/firestore/firestore';
import { Observable } from 'rxjs/Observable';

Queremos a Songinterface para uma verificação de tipo restrita, FirestoreProviderpara se comunicar com o banco de dados e Observabletambém para verificação de tipo, nosso provedor retornará um AngularFirestoreCollection que transformaremos em um observável para exibir em nossa visualização.

Então, dentro de nossa classe, queremos criar a songListpropriedade, vamos usá-la para exibir as músicas no HTML e injetar o provedor firestore no construtor.

public songList: Observable<Song[]>;
constructor(
  public navCtrl: NavController,
  public firestoreProvider: FirestoreProvider
) {}

E, por último, queremos esperar até que a página carregue e buscar a lista do nosso provedor:

ionViewDidLoad() {
  this.songList = this.firestoreProvider.getSongList().valueChanges();
}

.valueChanges()método pega o AngularFirestoreCollection e o transforma em um tipo Observable of Songs.

Agora podemos ir para home.htmldentro e dentro da <ion-content>nossa lista de músicas para exibir todas as músicas no banco de dados.

<ion-content>
  <ion-card *ngFor="let song of songList | async" 
    (click)="goToDetailPage(song)">
    <ion-card-header>
      {{ song.songName }}
    </ion-card-header>
    <ion-card-content>
      Artist Name: {{ song.artistName }}
    </ion-card-content>
  </ion-card>
</ion-content>

Estamos apenas mostrando o nome da música e o nome do artista, e estamos adicionando um evento de clique ao nosso cartão, uma vez que o usuário clica no cartão, ele deve acionar a goToDetailPage()função e passar todo o objeto da música como um parâmetro.

Nós não criamos essa função, então vamos criar um momento para criá-la em nossa homepage:

goToDetailPage(song: Song): void {
  this.navCtrl.push('DetailPage', { song: song });
}

A função navega o usuário até a página Detail e passa todo o objeto da música como um parâmetro de navegação. Na próxima seção, usaremos esse parâmetro de navegação para exibir os dados da música inteira na página de detalhes.

Por enquanto, pegue um biscoito ou algo assim, você já leu muito, e seus níveis de açúcar podem precisar de um impulso. Vejo vocês em alguns minutos na próxima seção🙂

Passo # 4: Navegue até a página de detalhes de um item.

Na etapa anterior, criamos uma função que nos leva à página de detalhes com as informações da música e, agora, vamos usar essas informações e exibi-las para o usuário ver.

Em vez de falar com o provedor para obter o registro da música, estamos passando a música inteira como um parâmetro de navegação, portanto, não precisamos importar nosso provedor do firestore agora.

A primeira coisa que faremos é detail.htmlcriar uma visualização básica que exiba todos os dados que temos para nossa música:

<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      {{ song.songName }}
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <h3> Artist </h3>
  <p>
    The song {{ song.songName }} was released by {{ song.artistName }}.
  </p>

  <h3> Album </h3>
  <p>
    It was part of the {{ song.albumName }} album.
  </p>

  <h3> Description </h3>
  <p>
    {{ song.songDescription }}
  </p>
</ion-content>

Estamos mostrando o nome da música na barra de navegação e adicionamos o restante dos dados ao conteúdo da página.

Agora vamos pular detail.tspara que possamos fazer o songcontrário, isso irá cometer erros.

Tudo que você precisa fazer é criar uma propriedade songdo tipo Song, para isso precisamos importar a Songinterface.

Então, você deseja obter o parâmetro de navegação que enviamos para a página e atribuir seu valor à songpropriedade que você criou.

import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { Song } from '../../models/song.interface';

@IonicPage()
@Component({
  selector: 'page-detail',
  templateUrl: 'detail.html',
})
export class DetailPage {
  public song: Song;
  constructor(public navCtrl: NavController, public navParams: NavParams) {
    this.song = this.navParams.get('song');
  }
}

Você deve fazer um teste agora mesmo, pois ionic serveseu aplicativo deve estar funcionando, e você deve ser capaz de criar novas músicas, mostrar a lista de músicas e entrar na página de detalhes de uma música.

Etapa 5: excluir um item da lista.

Na última parte do tutorial vamos adicionar um botão dentro da DetailPage, esse botão dará ao usuário a capacidade de remover músicas da lista.

Primeiro, abra detail.htmle crie o botão, nada muito chique, um botão regular que chame a função remove fará, configure-o imediatamente antes da tag de conteúdo iônico de fechamento.

<button ion-button block (click)="deleteSong(song.id, song.songName)">
    DELETE SONG
  </button>
</ion-content>

Agora vá para o detail.tse crie a deleteSong()função, ele deve levar 2 parâmetros, o ID da música e o nome da música:

deleteSong(songId: string, songName: string): void {}

A função deve acionar um alerta que solicita ao usuário uma confirmação e, se o usuário aceitar a confirmação, deverá chamar a função de exclusão do provedor e retornar à página anterior ( Nossa home page ou página de listagem ).

deleteSong(songId: string, songName: string): void {
    const alert: Alert = this.alertCtrl.create({
      message: `Are you sure you want to delete ${songName} from your list?`,
      buttons: [
        {
          text: 'Cancel',
          handler: () => {
            console.log('Clicked Cancel');
          },
        },
        {
          text: 'OK',
          handler: () => {
            this.firestoreProvider.deleteSong(songId).then(() => {
              this.navCtrl.pop();
            });
          },
        },
      ],
    });
    alert.present();
  }

NOTA: Certifique-se de importar Alert, AlertController e nosso FirestoreProvider para que isso funcione.

Agora, tudo o que precisamos fazer é ir ao nosso provedor e criar a função de exclusão:

deleteSong(songId: string): Promise<void> {
  return this.firestore.doc(`songList/${songId}`).delete();
}

A função usa o ID da música como um parâmetro e, em seguida, usa-a para criar uma referência a esse documento específico no banco de dados. Por último, chama o .delete()método nesse documento.

E é isso. Você deve ter uma funcionalidade Mestre / Detalhe totalmente funcional na qual possa listar objetos, criar novos objetos e excluir objetos do banco de dados.🙂

Próximos passos

Parabéns, esse foi longo, mas estou certo de que você agora entende mais sobre o Firestore e como usá-lo com o Firebase.

Se você quiser saber mais sobre o Firestore e começar a criar aplicativos Ionic mais completos, criei um Crash Course que aborda a teoria por trás do que vimos aqui e também inclui os disparadores do Cloud Functions para as regras de segurança do Firestore e do Firestore.

VOCÊ PODE RECEBER GRATUITAMENTE AQUI .

FONTE: https://javebratt.com/crud-ionic-firestore/

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s