Formularios con ngModel en Angular

Intermedio
Angular
Angular
Actualizado: 27/08/2024

¡Desbloquea el curso completo!

IA
Ejercicios
Certificado
Entrar

ngModel es una directiva de Angular que se utiliza para crear una conexión bidireccional entre el modelo de datos en tu componente y los elementos del formulario en la vista. 

¿Te está gustando esta lección?

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

Esta directiva pertenece al módulo FormsModule, lo que implica que debe importarse en tu aplicación para poder ser utilizada.

La conexión bidireccional proporcionada por ngModel permite que cualquier cambio en el valor del formulario se refleje automáticamente en la propiedad correspondiente del modelo, y viceversa, cualquier cambio en el modelo también se refleja automáticamente en el formulario. Esto es especialmente útil para mantener sincronizados los datos y la interfaz de usuario (UI) sin necesidad de escribir código adicional para observar los cambios.

¿Cómo se utiliza ngModel?

Para usar ngModel en un formulario sencillo, se pueden seguir los siguientes pasos:

  1.- Importar FormsModule

Se debe importar el módulo FormsModule de @angular/forms en el módulo donde se va a usar el formulario.

// app.module.ts
import { FormsModule } from '@angular/forms';
import { NgModule } from '@angular/core';

@NgModule({
  imports: [ FormsModule ],
  // ...
})
export class AppModule { }

Para aplicaciones standalone (sin módulo principal):

En aplicaciones standalone, se debe importar FormsModule directamente en el componente donde se utilizará ngModel.

// mi-formulario.component.ts
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-mi-formulario',
  standalone: true,
  imports: [FormsModule, CommonModule],
  templateUrl: './mi-formulario.component.html',
  styleUrls: ['./mi-formulario.component.css']
})
export class MiFormularioComponent {
  // ...
}

  2.- Crear un componente para el formulario

Ejecutar el siguiente comando para generar un nuevo componente llamado mi-formulario:

ng generate component mi-formulario

Para aplicaciones standalone, usar:

ng generate component mi-formulario --standalone

  3.- Definir la estructura del formulario en la plantilla del componente

En el archivo HTML del componente,  puedes usar la sintaxis [(ngModel)] para vincular un campo de formulario a una propiedad del modelo de tu componente:

<!-- mi-formulario.component.html -->
<form (ngSubmit)="onSubmit()">
    <div>
        <label for="nombre">Nombre:</label>
        <input type="text" id="nombre" [(ngModel)]="nombre" name="nombre" required>
    </div>
    <div>
        <label for="email">Email:</label>
        <input type="email" id="email" [(ngModel)]="email" name="email" required>
    </div>

    <button type="submit">Enviar</button>
</form>

  4.- Vincular los elementos del formulario a las propiedades del componente

En el archivo TypeScript del componente, se debe declarar la propiedad que se va a enlazar.

// mi-formulario.component.ts
import { Component } from '@angular/core';

@Component({
    selector: 'app-mi-formulario',
    templateUrl: './mi-formulario.component.html',
    styleUrls: ['./mi-formulario.component.css']
})
export class MiFormularioComponent {
    nombre = '';
    email = '';

    onSubmit() {
        console.log('Nombre:', this.nombre);
        console.log('Email:', this.email);
    }
}

En este ejemplo:

  • Usamos ngModel para vincular los campos del formulario con las propiedades del objeto usuario.
  • Aplicamos validaciones básicas como required y email.
  • El botón de envío se deshabilita si el formulario no es válido.
  • Mostramos los datos enviados después de que el formulario se haya enviado.

Este ejemplo ilustra cómo ngModel facilita la creación de formularios simples con validación básica y enlace bidireccional de datos.

También se utilizó la directiva [(ngModel)] para vincular cada campo de entrada a una propiedad del componente y se añadió la etiqueta required para indicar que ambos campos son obligatorios.

Inicialización de valores

Puedes inicializar las propiedades del modelo antes de que se cargue el componente y, automáticamente, estos valores aparecerán en los campos de los formularios vinculados:

export class AppComponent {
    nombre: string = 'Juan';
}

Con este código, el campo de entrada se inicializará con el valor "Juan".

Uso con selectores y otros controles

ngModel se puede usar no solo con inputs de texto, sino también con distintos tipos de inputs y selectores:

<select [(ngModel)]="paisSeleccionado" name="pais">
  @for (pais of paises; track pais) {
    <option [value]="pais">{{pais}}</option>
  }
</select>

En el componente:

export class AppComponent {
  paises: string[] = ['España', 'Francia', 'Alemania'];
  paisSeleccionado: string = this.paises[0];
}

Validación de formularios

Una de las ventajas de usar NgModel es la facilidad de implementar validaciones.

Angular proporciona varias directivas para validaciones predefinidas que se pueden aplicar directamente a los elementos del formulario:

  1. required: Campo obligatorio.
  2. minlength: Número mínimo de caracteres.
  3. maxlength: Número máximo de caracteres.
  4. pattern: Expresión regular que debe cumplir el valor.
<form #formulario="ngForm">
  <input name="nombre" [(ngModel)]="nombre" required minlength="5" maxlength="20" pattern="[a-zA-Z ]*">
  @if (formulario.controls['nombre'].errors?.['required']) {
    <div>El nombre es obligatorio</div>
  }
  @if (formulario.controls['nombre'].errors?.['minlength']) {
    <div>El nombre debe tener al menos 5 caracteres</div>
  }
  @if (formulario.controls['nombre'].errors?.['maxlength']) {
    <div>El nombre no puede exceder 20 caracteres</div>
  }
  @if (formulario.controls['nombre'].errors?.['pattern']) {
    <div>El nombre solo puede contener letras y espacios</div>
  }
</form>

ngModel con objetos complejos

ngModel no solo se limita a trabajar con tipos de datos simples, sino que también puede manejar objetos más complejos. Esto es útil cuando necesitas crear formularios que representen entidades con múltiples propiedades.

Veamos un ejemplo sencillo de cómo usar ngModel con un objeto que tiene propiedades anidadas:

Primero, definimos el modelo de datos en el componente:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  usuario = {
    nombre: '',
    direccion: {
      calle: '',
      ciudad: ''
    }
  };

  getErrorMessages(control: AbstractControl | null): string[] {
    if (!control || !control.errors) return [];
    
    const messages = [];
    if (control.errors['required']) {
      messages.push('Este campo es obligatorio');
    }
    // Puedes agregar más mensajes para otros tipos de errores aquí
    
    return messages;
  }

  onSubmit() {
    console.log('Datos del usuario:', this.usuario);
  }
}

Luego, creamos el formulario en la plantilla HTML:

<!-- app.component.html -->
<form (ngSubmit)="onSubmit()" #formulario="ngForm">
  <div>
    <label for="nombre">Nombre:</label>
    <input id="nombre" [(ngModel)]="usuario.nombre" name="nombre" required>
  </div>

  <div ngModelGroup="direccion">
    <div>
      <label for="calle">Calle:</label>
      <input id="calle" [(ngModel)]="usuario.direccion.calle" name="calle" required>
    </div>
    <div>
      <label for="ciudad">Ciudad:</label>
      <input id="ciudad" [(ngModel)]="usuario.direccion.ciudad" name="ciudad" required>
    </div>
  </div>

  <button type="submit" [disabled]="!formulario.form.valid">Enviar</button>
</form>

En este ejemplo:

  • Usamos [(ngModel)] para vincular cada campo del formulario con las propiedades del objeto usuario.
  • Utilizamos ngModelGroup para agrupar los campos relacionados con la dirección.
  • Aplicamos validaciones básicas como required.
  • El botón de envío se deshabilita si el formulario no es válido.

Para mostrar mensajes de error, podemos agregar al campo Nombre:

<div>
  <label for="nombre">Nombre:</label>
  <input id="nombre" [(ngModel)]="usuario.nombre" name="nombre" required>
  @for (error of getErrorMessages(formulario.controls['nombre']); track error) {
    <span class="error-message">{{ error }}</span>
  }
</div>

Esta estructura permite manejar objetos complejos de forma sencilla, manteniendo la sincronización entre el modelo de datos y el formulario. Además, facilita la agrupación lógica de campos relacionados y la aplicación de validaciones.

Ventajas y desventajas de ngModel

Ventajas:

  1. Facilidad de uso: ngModel simplifica el código al minimizar la cantidad de lógica requerida para el enlace de datos.
  2. Rapidez de desarrollo: Ideal para prototipos y proyectos pequeños donde la velocidad de desarrollo es crucial.

Desventajas:

  1. Menos control: Ofrece menos control en comparación con las formas reactivas.
  2. Rendimiento: No es la opción más eficiente para formularios complejos y dinámicos.

Aprendizajes de esta lección

  1. Comprender el concepto de ngModel en Angular.
  2. Aprender a importar FormsModule para usar ngModel.
  3. Entender cómo usar ngModel para crear formularios.
  4. Conocer las ventajas y desventajas de usar ngModel.

Completa Angular y certifícate

Únete a nuestra plataforma y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración