Primeros Pasos: Angular 10 con FireBase.
Tags: angular, googlecloud, typescript, database
Published: 2020-06-30 03:59:02

Despues de tener nuestro primer proyecto creado con Angular 10, vamos a hacer una conexion con FireBase en su ultima version de Junio 2020.  Para esto ingresamos a la consola de FireBase con nuestra cuenta de Google.
[https://console.firebase.google.com/](https://console.firebase.google.com/)

#Creando FireBase RealTime Database.
Creamos un nuevo Proyecto, al cual para este escenario le pondre el nombre del Proyecto:  Angular-Typescript.  Creamos un RealTime Database; en Database, Create Database.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/swbdedt5kj5cjf2f0b33.png)
Create Database habilitando el modo de pruebas.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o0gowf3z9roes1do5504.png)
Para evitar en las pruebas la autenticacion en la lectura o escritura modificamos las reglas:
```json
{
  "rules": {
    ".read": "auth == null",
    ".write": "auth == null"
  }
}
```
Obtenemos el código para configurar en Angular nuestra Database.
![FireBase Angular](https://dev-to-uploads.s3.amazonaws.com/i/9jknc8bg2zdfbjdbjedy.png)

#Configurar Angular para FireBase
Vamos en nuestro código a src/environments/environments.ts.
Modificamos el archivo de la siguiente manera:
![Ejemplo firebase](https://dev-to-uploads.s3.amazonaws.com/i/gqazr20devbvtsl2892o.png)
En el terminal instalamos los paquetes de FireBase:
```
npm install -save firebase @angular/fire
```
Incluir en el módulo principal los módulos de Angular para FireBase.  Asi quedara nuestro archivo src/app/app.module.ts:
```typescript
import { BrowserModule } from '@angular/platform-browser';
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 'src/environments/environment';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFireDatabaseModule,
    AppRoutingModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
```
# Creamos una Interface.
en la carpeta app creamos una carpeta interfaces, y en ella creamos nuestra primer interface, por ejemplo jugador.ts
```typescript
export interface Jugador {
  $key?: string; //Angular necesita este campo.
  nombre: string;
  apellido: string;
  posicion: NumeroPosicion;
  peso: number;
  altura: number;
  nacionalidad: Paises;
  zurdo: boolean;
}
```
Paises es tomado de un gist al buscar en google: typescript enum countries.  Tanto posicion como nacionalidad son dos enum.

Creamos una segunda interface para los equipos:
```typescript
import { Jugador, Paises } from './jugador';

export interface Equipo {
  $key?: string;
  nombre: string;
  pais: Paises;
  players: Jugador[];
}
```
Ahora crearemos los endpoints, creamos la carpeta services en app.  La idea es tener un servicio para cada una de la logica de datos.  Creamos un servicio mediante la consola y el AngularCLI.  Dentro de la carpeta servicios en la terminal:
```
ng g service jugador
```
Despues de creados los dos archivos (uno con el codigo, y otro con el unit test).  Debemos importar el servicio en app.module.ts
```typescript
import { JugadorService } from './services/jugador.service';
```
y en providers:
```typescript
  providers: [JugadorService],
```
Ahora en el servicio jugadores vamos a crear todas las acciones que podemos hacer con esa clase:
```typescript
import { Jugador } from './../interfaces/jugador';
import { Injectable } from '@angular/core';
import { AngularFireList, AngularFireDatabase } from '@angular/fire/database';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
//Este decorador nos permite tener una instancia de JugadorService para el modulo.
@Injectable({
  providedIn: 'root',
})
export class JugadorService {
  //Este contendra una Coleccion de Jugadores de la DB.
  private jugadoresDB: AngularFireList<Jugador>;

  constructor(private db: AngularFireDatabase) {
    //? Accedemos a la base de datos de firebase.
    //? Vamos a acceder la lista de jugadores en la db.
    //? y se implementa la funcionalidad en el segundo argumento.
    //? La referencia que es nuestra lista de jugadores, se va a ordenar por nombre.
    this.jugadoresDB = this.db.list('/jugadores', (ref) =>
      ref.orderByChild('nombre')
    );
  }

  //Devuelve un Observable de tipo Jugador Array.
  getJugadores(): Observable<Jugador[]> {
    //? this.jugadoresDB ya tiene la base de datos.
    //? snapshotChanges obtiene la informacion en este momento.
    //? Obtiene los datos junto con la Key
    //? Con Pipe permite hacer modificaciones
    //? Con Map haremos un cambio, que por cada uno de los jugadores retornaremos la informacion,
    //? y se Agregue una Key.
    //? El formato de key siempre es $key.
    //? Payload es por donde esta viajando la data.
    return this.jugadoresDB.snapshotChanges().pipe(
      //?A veces hay que importar map manualmente de rsjs/operators
      map((changes) => {
        return changes.map((c) => ({
          $key: c.payload.key,
          ...c.payload.val(),
        }));
      })
    );
  }

  //Metodo para crear un nuevo jugador en la DB
  addJugador(jugador: Jugador) {
    //?Con esto FireBase se encarga de todo,
    //?no hay que pensar en endpoints o si esta o no creada la tabla.
    //?Adicionamos un nuevo record a la tabla.
    return this.jugadoresDB.push(jugador);
  }

  //Borrar un Jugador de la DB
  deleteJugador(id: string) {
    //? Que base de datos afectaremos? Jugadores.
    //? El id del jugador que deseamos eliminar.
    this.db.list('/jugadores').remove(id);
  }

  //Editar un Jugador
  editJugador(newJugadorData) {
    //? Salvamos el Key.
    //? Eliminamos el registro anterior con el Key.
    //? Nuevamente asignamos a ese registro la nueva información en la base de datos.
    //? FireBase no acepta que ya se contenga una Key, por eso se hizo la Key opcional.
    //? Al borrar o actualizar daria problema sino fuera opcional.
    const $key = newJugadorData.$key;
    delete newJugadorData.$key;
    this.db.list('/jugadores').update($key, newJugadorData);
  }
}
```
Ahora hacemos lo mismo pero para Teams, apuntando a Teams, adicionamos a providers en el module del app.
```
ng g service equipo
```
```typescript
import { EquipoService } from './services/equipo.service';  providers: [JugadorService, EquipoService],
```

#Componentes
Para generar los componentes usamos el CLI, vamos a crear la tabla de equipos como un componente.  Creamos una carpeta llamada componentes:
```
ng g component equipo-table
```