Ir al contenido

Tutorial: Crear un artista desde el front

Al terminar este tutorial vas a ser capaz de:

  • Construir un formulario con Reactive Forms (FormGroup, FormControl, Validators).
  • Distinguir el tipo de lo que envías (sin id, sin datos derivados) del tipo de lo que recibes de vuelta, usando Omit<T, K>.
  • Crear tu primer servicio Angular (@Injectable({ providedIn: 'root' })) con un método de escritura, usando HttpClient.post().
  • Manejar los dos desenlaces de una petición con .subscribe({ next, error }).

Prerrequisitos: tener tu componente de listado (el que construiste siguiendo el taller de httpResource, adaptado a tu propio módulo en el Release 1) apuntando a tu propio backend, y que ese backend responda POST /artistas con 201 Created, como quedó en el tutorial de agregar el endpoint POST.


Genera el componente:

Ventana de terminal
ng generate component artist-create

Y arma su formulario con Reactive Forms, siguiendo el patrón que vio en Formularios Reactivos:

artist-create.ts
artistaForm: FormGroup<{
nombre: FormControl<string>;
fotoArtistaUrl: FormControl<string>;
paisOrigen: FormControl<string>;
fechaNacimiento: FormControl<string>;
biografia: FormControl<string>;
}> = new FormGroup({
nombre: new FormControl<string>('', { nonNullable: true, validators: [Validators.required] }),
fotoArtistaUrl: new FormControl<string>('', { nonNullable: true, validators: [Validators.required] }),
paisOrigen: new FormControl<string>('', { nonNullable: true, validators: [Validators.required] }),
fechaNacimiento: new FormControl<string>('', { nonNullable: true, validators: [Validators.required] }),
biografia: new FormControl<string>('', { nonNullable: true, validators: [Validators.required] }),
});

En el template, un <input formControlName="..."> por campo, y los dos botones:

artist-create.html
<form [formGroup]="artistaForm" (ngSubmit)="guardar()">
<input formControlName="nombre" />
<input formControlName="fotoArtistaUrl" />
<input formControlName="paisOrigen" />
<input formControlName="fechaNacimiento" />
<textarea formControlName="biografia"></textarea>
<button type="submit" [disabled]="artistaForm.invalid || guardando()">
@if (guardando()) { Guardando… } @else { Crear artista }
</button>
<button type="button" [disabled]="guardando()" (click)="cancelar()">
Cancelar
</button>
</form>

guardando es un signal<boolean> propio del componente, para deshabilitar los botones mientras el POST está en curso. Va a cobrar sentido en el paso 5.


3. NuevoArtista: un tipo distinto para lo que se envía

Sección titulada «3. NuevoArtista: un tipo distinto para lo que se envía»

Lo que viaja en el POST no es un Artista completo: no hay id todavía (lo asigna el backend) y no hay albumes (este formulario no los pide). En vez de declarar una interface nueva y repetir los atributos, use Omit:

artista.model.ts
export type NuevoArtista = Omit<Artista, 'id' | 'albumes'>;

4. Crear ArtistaService, con un método para escribir

Sección titulada «4. Crear ArtistaService, con un método para escribir»

Hasta ahora ningún componente de su app usaba un servicio: su componente de listado llama httpResource directamente. Este formulario va a ser distinto — necesita enviar datos, y la teoría ya le advirtió la regla:

Genere el servicio:

Ventana de terminal
ng generate service artista

Y agregue el método de escritura, con HttpClient.post():

artista.service.ts
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Artista, NuevoArtista } from './artista.model';
import { environment } from '../environments/environment';
@Injectable({ providedIn: 'root' })
export class ArtistaService {
private http: HttpClient = inject(HttpClient);
crear(nuevoArtista: NuevoArtista): Observable<Artista> {
return this.http.post<Artista>(environment.gistUrl, nuevoArtista);
}
}

De vuelta en ArtistCreate, guardar() llama al servicio y maneja los dos desenlaces posibles con .subscribe({ next, error }) — el mismo patrón que vio en HttpClient: cuando necesita actuar:

artist-create.ts
guardando = signal(false);
exito = signal(false);
error = signal(false);
private artistaService = inject(ArtistaService);
guardar(): void {
if (this.artistaForm.invalid) return;
this.guardando.set(true);
this.exito.set(false);
this.error.set(false);
const nuevoArtista: NuevoArtista = this.artistaForm.getRawValue();
this.artistaService.crear(nuevoArtista).subscribe({
next: (): void => {
this.guardando.set(false);
this.exito.set(true);
this.artistaForm.reset();
},
error: (): void => {
this.guardando.set(false);
this.error.set(true);
},
});
}
cancelar(): void {
this.artistaForm.reset();
this.exito.set(false);
this.error.set(false);
}

Corre tu front (ng serve) junto con tu backend. Llena el formulario y haz submit:

  • El botón debería decir “Guardando…” brevemente, y luego volver a “Crear artista”.
  • El formulario debería vaciarse y debería verse su mensaje de éxito.
  • En la pestaña de Red del navegador (Network), debería ver la petición POST /artistas saliendo, con el body de NuevoArtista, y la respuesta con 201 Created.

Si el backend no está corriendo, pruebe primero un error a propósito: debería ver el mensaje de error de ArtistCreate, en vez del de éxito.


Al final de este tutorial tienes:

  • ArtistCreate, un formulario con Reactive Forms que crea un artista con POST.
  • NuevoArtista, un tipo derivado de Artista con Omit.
  • Tu primer servicio Angular, ArtistaService, con un método crear() que funciona de punta a punta.

Lo que viene después: