Publicada: diciembre 05 2022

Angular 14 - Formulario dinámico para agregar/editar que admite el modo de creación y actualización

Tutorial creado con Angular 14.2.12

Otras versiones disponibles:

Esta es una publicación rápida sobre cómo crear un formulario que admita agregar y editar datos en Angular 14 con formularios reactivos.

Los formularios para crear y actualizar registros a menudo pueden contener mucho del mismo código. Si el código es lo suficientemente similar, puede tener más sentido combinar la funcionalidad en una sola forma dinámica que mantener dos archivos que son casi idénticos.

El código de ejemplo es de un tutorial de Angular Auth + CRUD que publiqué recientemente y que permite agregar y editar datos de usuario después de iniciar sesión. Para ver el tutorial completo, incluida una demostración en vivo, consulte Angular 14 - Ejemplo y Tutorial de Registro de Usuario e Inicio de Sesión.

 

Plantilla de componente de agregar/editar usuarios

Ruta: /src/app/users/add-edit.component.html

La plantilla de componente para agregar/editar usuarios contiene un formulario dinámico que permite agregar y editar usuarios. El formulario está en modo editar cuando hay una propiedad id de usuario en la ruta actual, de lo contrario, está en modo agregar.

En el modo de edición, el formulario se completa previamente con los detalles del usuario obtenidos de la API y el campo de contraseña es opcional. El comportamiento dinámico se implementa en el componente de adición/edición de usuarios.

<h1>{{title}}</h1>
<form *ngIf="!loading" [formGroup]="form" (ngSubmit)="onSubmit()">
    <div class="row">
        <div class="mb-3 col">
            <label class="form-label">First Name</label>
            <input type="text" formControlName="firstName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.firstName.errors }" />
            <div *ngIf="submitted && f.firstName.errors" class="invalid-feedback">
                <div *ngIf="f.firstName.errors.required">First Name is required</div>
            </div>
        </div>
        <div class="mb-3 col">
            <label class="form-label">Last Name</label>
            <input type="text" formControlName="lastName" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.lastName.errors }" />
            <div *ngIf="submitted && f.lastName.errors" class="invalid-feedback">
                <div *ngIf="f.lastName.errors.required">Last Name is required</div>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="mb-3 col">
            <label class="form-label">Username</label>
            <input type="text" formControlName="username" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.username.errors }" />
            <div *ngIf="submitted && f.username.errors" class="invalid-feedback">
                <div *ngIf="f.username.errors.required">Username is required</div>
            </div>
        </div>
        <div class="mb-3 col">
            <label class="form-label">
                Password
                <em *ngIf="id">(Leave blank to keep the same password)</em>
            </label>
            <input type="password" formControlName="password" class="form-control" [ngClass]="{ 'is-invalid': submitted && f.password.errors }" />
            <div *ngIf="submitted && f.password.errors" class="invalid-feedback">
                <div *ngIf="f.password.errors.required">Password is required</div>
                <div *ngIf="f.password.errors.minlength">Password must be at least 6 characters</div>
            </div>
        </div>
    </div>
    <div class="mb-3">
        <button [disabled]="submitting" class="btn btn-primary">
            <span *ngIf="submitting" class="spinner-border spinner-border-sm me-1"></span>
            Save
        </button>
        <a routerLink="/users" class="btn btn-link">Cancel</a>
    </div>
</form>
<div *ngIf="loading" class="text-center m-5">
    <span class="spinner-border spinner-border-lg align-center"></span>
</div>
 

Componente de agregar/editar usuarios

Ruta: /src/app/users/add-edit.component.ts

El componente de agregar/editar usuarios se usa tanto para agregar como para editar usuarios en la aplicación de tutorial angular, el componente está en modo editar cuando hay un parámetro de ruta id de usuario , de lo contrario, está en modo agregar.

En el modo agregar, el campo de contraseña es obligatorio y los campos del formulario están vacíos de forma predeterminada. En el modo editar, el campo de contraseña es opcional y el formulario se completa previamente con los detalles del usuario especificado, que se obtienen de la API con el servicio de cuenta. Para obtener más información sobre la validación con formularios reactivos, consulte Angular 14 - Ejemplo de Validación de Formularios Reactivos (Reactive Forms).

Al enviar, se crea o actualiza un usuario llamando al servicio de la cuenta y, en caso de éxito, se le redirige a la página de la lista de usuarios con un mensaje de éxito.

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { first } from 'rxjs/operators';

import { AccountService, AlertService } from '@app/_services';

@Component({ templateUrl: 'add-edit.component.html' })
export class AddEditComponent implements OnInit {
    form!: FormGroup;
    id?: string;
    title!: string;
    loading = false;
    submitting = false;
    submitted = false;

    constructor(
        private formBuilder: FormBuilder,
        private route: ActivatedRoute,
        private router: Router,
        private accountService: AccountService,
        private alertService: AlertService
    ) { }

    ngOnInit() {
        this.id = this.route.snapshot.params['id'];

        // form with validation rules
        this.form = this.formBuilder.group({
            firstName: ['', Validators.required],
            lastName: ['', Validators.required],
            username: ['', Validators.required],
            // password only required in add mode
            password: ['', [Validators.minLength(6), ...(!this.id ? [Validators.required] : [])]]
        });

        this.title = 'Add User';
        if (this.id) {
            // edit mode
            this.title = 'Edit User';
            this.loading = true;
            this.accountService.getById(this.id)
                .pipe(first())
                .subscribe(x => {
                    this.form.patchValue(x);
                    this.loading = false;
                });
        }
    }

    // convenience getter for easy access to form fields
    get f() { return this.form.controls; }

    onSubmit() {
        this.submitted = true;

        // reset alerts on submit
        this.alertService.clear();

        // stop here if form is invalid
        if (this.form.invalid) {
            return;
        }

        this.submitting = true;
        this.saveUser()
            .pipe(first())
            .subscribe({
                next: () => {
                    this.alertService.success('User saved', { keepAfterRouteChange: true });
                    this.router.navigateByUrl('/users');
                },
                error: error => {
                    this.alertService.error(error);
                    this.submitting = false;
                }
            })
    }

    private saveUser() {
        // create or update user based on id param
        return this.id
            ? this.accountService.update(this.id!, this.form.value)
            : this.accountService.register(this.form.value);
    }
}
 

Módulo de enrutamiento de usuarios

Ruta: /src/app/users/users-routing.module.ts

El módulo de enrutamiento de usuarios define las rutas para la sección /users de la aplicación Angular. Incluye rutas para listar, agregar y editar usuarios, y una ruta principal para el LayoutComponent que contiene el código de diseño común para todas las páginas en la sección de usuarios.

Las rutas de agregar y editar tienen rutas diferentes ('add' & 'edit/:id') pero ambas cargan el mismo componente (AddEditComponent) que modifica dinámicamente su comportamiento en función de la ruta.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { LayoutComponent } from './layout.component';
import { ListComponent } from './list.component';
import { AddEditComponent } from './add-edit.component';

const routes: Routes = [
    {
        path: '', component: LayoutComponent,
        children: [
            { path: '', component: ListComponent },
            { path: 'add', component: AddEditComponent },
            { path: 'edit/:id', component: AddEditComponent }
        ]
    }
];

@NgModule({
    imports: [RouterModule.forChild(routes)],
    exports: [RouterModule]
})
export class UsersRoutingModule { }

 


Suscríbete o Sígueme para actualizaciones

Suscríbete a mi canal de YouTube o sígueme en Twitter, Facebook o GitHub para recibir notificaciones cuando publique contenido nuevo.

Aparte de la codificación...

Actualmente estoy intentando viajar por Australia en motocicleta con mi esposa Tina en un par de Royal Enfield Himalayan. Puedes seguir nuestras aventuras en YouTube, Instagram y Facebook.


¿Necesita Ayuda Angular 14?

Buscar fiverr para encontrar ayuda rápidamente de desarrolladores Angular 14 experimentados.