Tutorial: Crear un artista desde el front
1. Objetivos de aprendizaje
Sección titulada «1. Objetivos de aprendizaje»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, usandoOmit<T, K>. - Crear tu primer servicio Angular (
@Injectable({ providedIn: 'root' })) con un método de escritura, usandoHttpClient.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.
2. El formulario: ArtistCreate
Sección titulada «2. El formulario: ArtistCreate»Genera el componente:
ng generate component artist-createY arma su formulario con Reactive Forms, siguiendo el patrón que vio en Formularios Reactivos:
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:
<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:
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:
ng generate service artistaY agregue el método de escritura, con HttpClient.post():
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); }}5. guardar(): conectar todo
Sección titulada «5. guardar(): conectar todo»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:
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);}6. Verificar
Sección titulada «6. Verificar»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 /artistassaliendo, con el body deNuevoArtista, y la respuesta con201 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.
¿Dónde quedaste?
Sección titulada «¿Dónde quedaste?»Al final de este tutorial tienes:
ArtistCreate, un formulario con Reactive Forms que crea un artista conPOST.NuevoArtista, un tipo derivado deArtistaconOmit.- Tu primer servicio Angular,
ArtistaService, con un métodocrear()que funciona de punta a punta.
Lo que viene después:
- Tutorial: Compartir datos entre componentes con un servicio: vas a mover también la lectura a este mismo servicio, y vas a ver cómo dos componentes que no se conocen entre sí terminan compartiendo los mismos datos.