Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Angular
Code

Introducción a Formas Angular 4: Formas Reactivas

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Introduction to Forms in Angular 4.
Introduction to Forms in Angular 4: Template-Driven Forms
Introduction to Forms in Angular 4: Writing Custom Form Validators

Spanish (Español) translation by Jean Perez (you can also view the original English article)

Final product image
What You'll Be Creating

Esta es la segunda parte de la serie de introducción a formas en Angular 4. En la primera parte, hemos creado un formulario utilizando el enfoque orientado a la plantilla. Utilizamos las directivas tales como ngModel, ngModelGroup y ngForm para sobrealimentar los elementos del formulario. En este tutorial, nos va a tomar un enfoque diferente a la construcción de formas — la forma reactiva.

Formas Reactivas

Formas reactivas toman un enfoque diferente en comparación a la de los formularios basados en plantillas. Aquí, crear e inicializar los objetos de control de formulario en nuestra clase de componentes. Son objetos intermedios que sostienen el estado de forma. Luego ligarlos a los elementos de control de formulario en la plantilla.

El objeto del control de formulario escucha cualquier cambio en los valores de control de entrada, y que inmediatamente se reflejan en el estado del objeto. Puesto que el componente tiene acceso directo a la estructura del modelo de datos, se pueden sincronizar todos los cambios entre el modelo de datos, el objeto del control de formulario y los valores de control de entrada.

High level overview of Reactive forms using model-driven approach

Prácticamente hablando, si estamos construyendo una forma de actualizar el perfil de usuario, el modelo de datos es el objeto de usuario obtenido en el servidor. Por Convención, se almacena a menudo dentro de la propiedad del componente usuario (this.user). El objeto del control de formulario o el modelo de la forma estará obligado a elementos de control de forma real de la plantilla.

Ambos estos modelos deben tener estructuras similares, aunque no son idénticos. Sin embargo, los valores de entrada no deben entrar en el modelo de datos directamente. La imagen describe cómo el usuario de la plantilla hace su manera al modelo de formulario.

Vamos a empezar.

Requisitos Previos

No necesita haber seguido la primera parte de esta serie, por parte dos para tener sentido. Sin embargo, si usted es nuevo a formas en Angular, recomiendo ir a través de la estrategia basada en la plantilla. El código para este proyecto está disponible en mi repositorio de GitHub. Asegúrese de que está en la rama derecha y luego descargar el zip o, alternativamente, clonar el repositorio para ver la forma en acción.

Si prefiere empezar de cero en su lugar, asegúrese de que tener Angular CLI instalado. Utilice el comando de la ng para generar un nuevo proyecto.

A continuación, generar un nuevo componente para el SignupForm o crearlo manualmente.

Reemplace el contenido de app.component.html con esto:

Esta es la estructura de directorio para el src/ directorio. He quitado algunos archivos no esenciales para mantener las cosas simples.

Como se puede ver, un directorio para el componente de SignupForm se ha creado automáticamente. Es donde irá la mayor parte de nuestro código. También he creado un nuevo User.ts para el almacenamiento de nuestro modelo de usuario.

La Plantilla HTML

Antes de profundizar en la plantilla de la componente real, necesitamos tener una idea abstracta de lo que estamos construyendo. Así que aquí está la estructura de la forma que tengo en mi mente. El formulario de registro tiene varios campos, un select y un elemento casilla de verificación de entrada.

The HTML Template

Aquí está la plantilla HTML que utilizaremos para nuestra página de registro.

Plantilla HTML

Las clases CSS en la plantilla HTML son parte de la biblioteca Bootstrap utilizada para hacer las cosas bastante. Ya que esta es una no un tutorial de diseño, no hablar mucho sobre los aspectos CSS de la forma a menos que necesario.

Configuración de la Forma Básica

Para crear una forma reactiva, necesita importar el ReactiveFormsModule de @angular/forms y añadir a la matriz de las importaciones en app.module.ts.

app/app.Module.ts

A continuación, crear un modelo de usuario para el formulario de inscripción. Tampoco podemos utilizar una clase o una interfaz para crear el modelo. Para este tutorial, voy a exportar una clase con las siguientes propiedades.

app/User.ts

Ahora, crear una instancia del modelo de usuario en el componente SignupForm.

app/signup-form/signup-form.component.ts

Para el archivo de signup-form.component.html, voy a utilizar la misma plantilla HTML discutida anteriormente, pero con cambios menores. El formulario de registro tiene un campo select con una lista de opciones. Pesar de que funciona, lo haremos la forma Angular de bucle por la lista usando la Directiva ngFor.

app/signup-form/signup-form.component.html

Nota: Es posible que un error que no dice ningún proveedor para ControlContainer. El error aparece cuando un componente tiene un <form> etiqueta sin una directiva de formGroup. El error desaparecerá una vez que agregue una directiva de FormGroup más adelante en el tutorial.

Tenemos un componente, un modelo y una plantilla de formulario a mano. ¿Qué pasa ahora? Es hora de ensuciarse las manos así como con las API que necesita para crear formas reactivas. Esto incluye FormControl y FormGroup.

Seguimiento del Estado Usando FormControl

Construyendo formas con la estrategia de forma reactiva, no vendrá a través de las directivas ngModel y ngForm. En cambio, utilizamos la API de FormGroup y FormControl subyacente.

Un FormControl es una directiva que se utiliza para crear una instancia de FormControl que puede utilizar para hacer un seguimiento de estado de un elemento de forma particular y su estado de validación. Así es como funciona FormControl:

email es ahora una instancia FormControl, y usted puede enlazarlo a un elemento de control de entrada en la plantilla como sigue:

El elemento de formulario de plantilla está obligado ahora a la instancia FormControl en el componente. Lo significa es que cualquier cambio en el valor de control de entrada es reflejado en el otro extremo.

Un constructor FormControl acepta tres argumentos: un valor inicial, un array de validadores de sincronización y un array de validadores de async — y como puede haber adivinado, son opcionales. Que va cubriendo los dos primeros argumentos aquí.

Angular tiene un conjunto limitado de validadores incorporados. Los métodos de validación populares incluyen Validators.required, Validators.minLength, Validators.maxlength y Validators.pattern. Sin embargo, para usarlos, tienes que importar el API de validador primero.

Para registrarse en el formulario, tenemos varios campos de control de entrada (para correo electrónico y contraseña), un campo selector y un campo de casilla de verificación. ¿En lugar de crear objetos individuales FormControl, tendría más sentido para agrupar todos estos FormControls bajo una sola entidad? Esto es beneficioso porque ahora podemos localizar el valor y la validez de todos los objetos FormControl sub en un solo lugar. Es FormGroup. Por lo que se registrará a un padre FormGroup con el niño múltiples FormControls.

Grupo de Múltiples FormControls Con FormGroup

Para agregar un FormGroup, importar primero. A continuación, declarar signupForm como una propiedad de clase e inicialícela como sigue:

app/signup-form/signup-form.component.ts

Vincular el modelo de FormGroup al DOM como sigue:

app/signup-form/signup-form.component.html

[formGroup] = "signupForm" dice Angular que se quiere asociar esta forma de la FormGroup declarado en la clase de componente. Cuando Angular ve formControlName="email", comprueba si una instancia de FormControl con el email de valor clave dentro de la matriz FormGroup.

Igualmente, actualizar los otros elementos del formulario añadiendo un atributo  formControlName="value" como lo hiciste aquí.

Para ver si todo funciona como se esperaba, añadir lo siguiente después de la etiqueta form:

app/signup-form/signup-form.component.html

La propiedad SignupForm a través de la JsonPipe para representar el modelo como JSON en el navegador de la pipa. Esto es útil para la depuración y registro. Verá una salida JSON como esta.

Form state and validty in Model-driven forms

Hay dos cosas para notar aquí:

  1. El JSON no coincide exactamente con la estructura del modelo de usuario que creamos anteriormente.
  2. La signupForm.status muestra que el estado de forma es válido. Esto muestra claramente que el Validators.required en el campo de control de correo electrónico está funcionando como se esperaba.

Debe coincidir con la estructura del modelo de formulario y el modelo de datos.

Para obtener la estructura jerárquica del modelo de datos, debemos utilizar un FormGroup anidado. Además, siempre es una buena idea de haber relacionado con elementos de formulario en una sola FormGroup.

FormGroup Anidado

Crear un nuevo FormGroup para la contraseña.

app/signup-form/signup-form.component.ts

Ahora, para enlazar el nuevo modelo de formulario con el DOM, realice los siguientes cambios:

App/signup-form/signup-form.Component.html

formGroupName="password" realiza el enlace para la FormGroup anidado. Ahora, la estructura del modelo de formulario coincide con nuestras exigencias.

A continuación, es necesario validar los controles de formulario.

Validar el formulario

Contamos con una simple validación para el control de entrada de correo electrónico. Sin embargo, eso no es suficiente. Aquí está la lista completa de nuestros requisitos para la validación.

  • Todos los elementos de formulario control se requieren.
  • Desactivar el botón de enviar hasta el estado de forma es válido.
  • El campo email debe contener estrictamente un id de correo electrónico.
  • El campo contraseña debe tener una longitud mínima de 8.
Validating the form

La primera es fácil. Añadir Validator.required a todos los FormControls en el modelo de formulario.

App/signup-form/signup-form.Component.ts

A continuación, desactivar el botón mientras que la forma es válida.

App/signup-form/signup-form.Component.html

Para agregar una restricción en el correo electrónico, puede utilizar el valor por defecto Validators.email o crear un Validators.pattern() personalizado que especifica las expresiones regulares como la de abajo:

Utilice el validador de minLength para los campos de contraseña.

Es para la validación. Sin embargo, la lógica del modelo de formulario aparece desordenados y repetitivos. ¡Limpiar primero.

Refactorización del código utilizando FormBuilder

Angular le proporciona un azúcar de sintaxis para la creación de nuevas instancias de FormGroup y FormControl llamado FormBuilder. La API FormBuilder no hace nada especial que no sea de lo que hemos cubierto aquí.

Se simplifica el código y hace que el proceso de construcción de una forma fácil en los ojos. Para crear un FormBuilder, tienes que importarlo en signup-form.component.ts e inyecte el FormBuilder en el constructor.

App/signup-form/signup-form.Component.ts

En lugar de crear un FormGroup() nuevo, estamos usando this.fb.group para construir una forma. Excepción de la sintaxis, todo lo demás permanece igual.

App/signup-form/signup-form.Component.ts

Mostrar Errores de Validación

Para la visualización de los errores, voy a utilizar la ngIf directiva condicional en un elemento div. Comencemos con el campo control de entrada de correo electrónico:

Hay un par de temas aquí.

  1. ¿Dónde no invalid y pristine vienen?
  2. signupForm.controls.email.invalid es demasiado largo y profundo.
  3. El error no dice explícitamente por qué no es válido.

Para responder la primera pregunta, cada FormControl tiene ciertas propiedades como invalidvalidpristinedirtytouched, y untouched. Podemos utilizar estos para determinar si un mensaje de error o una advertencia debería mostrarse o no. La imagen de abajo describe cada una de las propiedades en detalle.

 FormControl Properties in Angular Reactive approach

Así que el elemento div con el *ngIf se mostrará solamente si el email no es válido. Sin embargo, el usuario será recibido con errores sobre los campos de entrada están en blanco, incluso antes de que tengan oportunidad de editar el formulario.

Para evitar este escenario, hemos añadido la segunda condición. El error aparece sólo después de que el control ha sido visitado.

Para deshacerse de la cadena larga de los nombres de método (signupForm.controls.email.invalid), voy a añadir un par de métodos getter de taquigrafía. Esto los mantiene más corto y accesible.

App/signup-form/signup-form.Component.ts

Para explicitar el error más, he añadido anidados ngIf condiciones siguientes:

App/signup-form/signup-form.Component.html

Utilizamos email.errors para comprobar todos los errores de validación posible y luego mostrarlos devuelve al usuario en forma de mensajes personalizados. Ahora, siga el mismo procedimiento para los otros elementos de formulario. Aquí es cómo yo he codificado la validación para las contraseñas y control de la entrada de los términos.

App/signup-form/signup-form.Component.html

Presentar el formulario utilizando ngSubmit

Casi hemos terminado con el formulario. Carece de la funcionalidad de enviar, que estamos a punto de poner en práctica ahora.

En el submit del formulario, los valores del modelo de formulario deben fluir hacia la propiedad del componente usuario.

App/signup-form/signup-form.Component.ts

Demostración Final

Aquí está la versión final de la aplicación. He añadido unas cuantas clases de Bootstrap para hacer la forma bastante.

Envolviéndolo

Si has estado siguiendo esta serie de tutoriales desde el principio, tuvimos una experiencia con dos tecnologías de construcción de forma popular en Angular. Las técnicas basadas en la plantilla y basada en el modelo son dos maneras de lograr lo mismo. Personalmente, prefiero utilizar las formas reactivas por las siguientes razones:

  • Toda la lógica de validación de formulario se encuentra en un solo lugar, dentro de su clase de componente. Esto es mucho más productivo que el enfoque de la plantilla, donde las directivas de ngModel se dispersan a través de la plantilla.
  • A diferencia de los formularios basados en plantillas, formas basadas en el modelo son más fáciles de probar. No tienes que recurrir a bibliotecas pruebas end-to-end para probar el formulario.
  • Lógica de validación irá dentro de la clase de componente y no en la plantilla.
  • Para un formulario con un gran número de elementos de formulario, este enfoque tiene algo llamado FormBuilder para facilitar la creación de objetos FormControl.

Nos faltó hacia fuera en una cosa, y está escribiendo un validador para la falta de coincidencia de contraseña. En la parte final de la serie, cubriremos todo lo que necesitas saber sobre cómo crear funciones de validador personalizado en Angular. Atentos hasta entonces.

Mientras tanto, hay un montón de armazones y bibliotecas para mantenerte ocupado, con un montón de artículos en Envato Market para leer, estudiar y usar.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.