Skip to content

sgarciaddev/ay-ingweb-ejemplo-form-ionic

Repository files navigation

Ayudantía Ingenieria web y móvil - Ejemplo validación formularios (Ionic/Angular)

Note

Para ver la versión de este proyecto utilizando Ionic/React, haz click aquí.

Datos

Ayudante: Sebastián García Delgadillo (@sgarciaddev).
Semestre: 1er/2024

ionic-badge-sm npm-badge-sm angular-badge-sm ts-badge-sm vscode-badge-sm

ios-development-badge-sm android-development-badge-sm

Índice

Detalles

Este proyecto contiene un ejemplo de aplicación de Ionic, utilizando Angular, donde se cubren 2 contenidos principales:

  1. Lectura de archivo JSON para cargar las regiones y comunas del país, dentro del formulario.
  2. Creación y validación de un formulario utilizando componentes de Ionic y conceptos de desarrollo en Angular.

Ejecución del proyecto

Para ejecutar este proyecto, se debe clonar el repositorio y ejecutar los siguientes comandos en la terminal:

git clone -b angular https://github.com/sgarciaddev/ay-ingweb-ejemplo-form-ionic.git

cd ay-ingweb-ejemplo-form-ionic

npm install

ionic serve

Archivos importantes

Nombre archivo Ruta completa Descripción
formulario.module.ts src/app/formulario/formulario.module.ts Archivo de módulo de la página de formulario.
Formulario.page.ts src/app/formulario/formulario.page.ts Archivo con la lógica de la página de formulario. Contiene toda la lógica de validación de formularios.
Formulario.page.html src/app/formulario/formulario.page.html Archivo HTML de la página de formulario. Contiene la estructura del formulario.
regiones.service.ts src/app/misc/regiones.service.ts Servicio de Angular para cargar las regiones y comunas del país.
Form-errors.ts src/app/misc/form-errors.ts Archivo con los mensajes de error de los campos del formulario.
Form-validations.ts src/app/misc/form-validators.ts Archivo con las funciones de validación de los campos del formulario.
regiones-comunas.json src/assets/regiones-comunas.json Archivo JSON con la información de las regiones y comunas del país.

Formularios

Para la creaciónd de formularios utilizando Ionic y Angular, se deben seguir los siguientes pasos:

Primero hay que agregar las importaciones necesarias en los archivos de Angular, para poder trabajar con formularios. Esto lo hacemos de la siguiente manera:

  1. En el archivo de módulo del componente o página, se deben importar los módulos necesarios para trabajar con formularios. En este caso, se importaron los módulos ReactiveFormsModule y FormsModule de Angular:
import { ReactiveFormsModule, FormsModule } from "@angular/forms";
  1. Luego, se deben agregar estos módulos al arreglo de imports del módulo:
@NgModule({
  imports: [
    ...
    FormsModule,
    ReactiveFormsModule,
  ],
});
  1. En el archivo de componente o página, se deben importar las clases necesarias para trabajar con formularios. En este caso, se importaron las clases FormGroup, FormControl, Validators y FormBuilder de Angular:
import { FormGroup, FormControl, Validators, FormBuilder } from "@angular/forms";
  1. Luego, se deben crear las instancias necesarias para trabajar con formularios. En este caso, se creó un atributo formulario de tipo FormGroup en el componente:
@Component({
  selector: 'app-formulario',
  templateUrl: 'formulario.page.html',
})
export class FormularioPage {
  formulario: FormGroup;
  ...
  constructor(private fb: FormBuilder, private regionService: RegionesService) {
  // Se inicializa el formulario con los campos requeridos y las validaciones
  this.formulario = this.fb.group({
    nombre: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(20)]],
    apellido: ['', [Validators.required, Validators.minLength(3), Validators.maxLength(20)]],
    rut: ['', [Validators.required, rutValidator]],
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]],
    passwordConfirm: ['', [Validators.required, passwordMatchValidator]],
    region: ['', Validators.required],
    comuna: [{value: '', disabled: true}, Validators.required],
    tyc: [false, Validators.requiredTrue],
  });
}}

En el ejemplo anterior, podemos ver que dentro del constructor del componente, se inicializa el formulario con los campos requeridos y las validaciones necesarias. En este caso, se utilizan las validaciones por defecto de Angular, como required, minLength, maxLength, email, entre otras. Además, se utilizan validaciones personalizadas, como rutValidator y passwordMatchValidator. Estas funciones se importan desde el archivo form-validators.ts. Ya con esto configurado, podemos proceder a crear el formulario en el archivo HTML.

Componentes de Ionic para formularios

Luego se debe crear el formulario en el componente de Angular. Para esto, se deben utilizar los componentes de Ionic dedicados a formularios. Puedes verlos en la documentación oficial de Ionic. En este ejemplo, se creó el siguiente formulario:

<form [formGroup]="formulario" (ngSubmit)="onSubmit()">
  <ion-item>
    <ion-input
      type="text"
      formControlName="nombre"
      labelPlacement="stacked"
      [errorText]="formError('nombre')"
    >
      <div slot="label">Nombre <ion-text color="danger">(requerido)</ion-text></div>
    </ion-input>
  </ion-item>

  <ion-item lines="none">
    <ion-input
      type="text"
      formControlName="apellido"
      labelPlacement="stacked"
      [errorText]="formError('apellido')"
    >
      <div slot="label">Apellido <ion-text color="danger">(requerido)</ion-text></div>
    </ion-input>
  </ion-item>

  <ion-item lines="none">
    <ion-input
      type="text"
      formControlName="rut"
      labelPlacement="stacked"
      [errorText]="formError('rut')"
    >
      <div slot="label">RUT <ion-text color="danger">(requerido)</ion-text></div>
    </ion-input>
  </ion-item>

  <ion-item lines="none">
    <ion-input
      type="email"
      formControlName="email"
      labelPlacement="stacked"
      [errorText]="formError('email')"
    >
      <div slot="label">Email <ion-text color="danger">(requerido)</ion-text></div>
    </ion-input>
  </ion-item>

  <ion-item lines="none">
    <ion-input
      type="password"
      formControlName="password"
      labelPlacement="stacked"
      [errorText]="formError('password')"
    >
      <div slot="label">Contraseña <ion-text color="danger">(requerido)</ion-text></div>
      <ion-input-password-toggle color="medium" slot="end"></ion-input-password-toggle>
    </ion-input>
  </ion-item>
  
  <ion-item lines="none">
    <ion-input
      type="password"
      formControlName="passwordConfirm"
      labelPlacement="stacked"
      [errorText]="formError('passwordConfirm')"
    >
      <div slot="label">Confirma tu contraseña <ion-text color="danger">(requerido)</ion-text></div>
      <ion-input-password-toggle color="medium" slot="end"></ion-input-password-toggle>
    </ion-input>
  </ion-item>

  <ion-item lines="full">
    <ion-select
      formControlName="region"
      interface="action-sheet"
      labelPlacement="stacked"
      (ionChange)="onRegionChange()"
    >
      <div slot="label">Región <ion-text color="danger">(requerido)</ion-text></div>

      <ion-select-option
        *ngFor="let region of regiones"
        [value]="region.valor"
      >
        {{region.nombre}}
      </ion-select-option
      >
    </ion-select>
  </ion-item>

  <ion-item lines="full">
    <ion-select
      formControlName="comuna"
      interface="action-sheet"
      labelPlacement="stacked"
    >
    <div slot="label">Comuna <ion-text color="danger">(requerido)</ion-text></div>
      <ion-select-option
        *ngFor="let comuna of comunas"
        [value]="comuna"
      >
        {{comuna}}
      </ion-select-option
      >
    </ion-select>
  </ion-item>

  <ion-item class="ion-margin-vertical" lines="none">
    <ion-toggle formControlName="tyc" labelPlacement="start" color="success">
      Acepto los términos y condiciones <ion-text color="danger">(requerido)</ion-text>
    </ion-toggle>
  </ion-item>

  <ion-button
    expand="full"
    class="ion-padding"
    type="submit"
    [color]="btnColor"
    [disabled]="!formulario.valid"
    >{{btnText}}</ion-button
  >
</form>

En este formulario, se utilizan los componentes de Ionic para formularios, como ion-input, ion-select, ion-toggle, entre otros. Cada componente tiene un atributo formControlName que se corresponde con el nombre del campo en el formulario de Angular. Además, se utilizan los atributos labelPlacement, errorText, interface, ionChange, entre otros, para personalizar el formulario. También se utilizan los atributos disabled y color de los componentes de Ionic para deshabilitar el botón de envío del formulario si no se cumplen las condiciones de validación.

Validación de formularios

La validación de formularios con Angular se realiza al momento de crear el formulario en el componente. En este caso, se utilizan las validaciones por defecto de Angular, como required, minLength, maxLength, email, entre otras. Para mostrar los mensajes de error en el formulario, se utilizan los elementos que se encuentran en el archivo form-errors.ts. Estos elementos se utilizan en el archivo HTML del formulario, y se muestran debajo de los campos correspondientes.

Validación personalizada

Además, se utilizan validaciones personalizadas, como rutValidator y passwordMatchValidator. Estas funciones se importan desde el archivo form-validators.ts. La validación personalizada se realiza en el archivo de componente, y se utiliza en el formulario de la siguiente manera:

this.formulario = this.fb.group({
  ...
  rut: ['', [Validators.required, rutValidator]],
  ...
  password: ['', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]],
  passwordConfirm: ['', [Validators.required, passwordMatchValidator]],
  ...
});

Por ejemplo, la validación del RUT se realiza con la función rutValidator, que se encuentra en el archivo form-validators.ts.

function validaDV(rut: string) {
  // Se separa el número del dígito verificador
  const [numero, dv] = rut.replace('-K', '-k').split('-');

  // Aquí se debe aplicar módulo 11. La función se extrajo de:
  // https://validarutchile.cl/calcular-rut-en-javascript.php
  // ! OJO: Es una función que se llama a sí misma.
  const dvVer = ((T: number): string => {
    let M = 0,
      S = 1;
    for (; T; T = Math.floor(T / 10)) S = (S + (T % 10) * (9 - (M++ % 6))) % 11;
    return S ? (S - 1).toString() : 'k';
  })(Number.parseInt(numero));

  // Se compara el dígito verificador calculado con el ingresado
  return dvVer == dv;
}

/**
 * Función que valida el formato y dígito verificador de un RUT
 * @param control Control que contiene el RUT a validar
 * @returns Objeto con la validación o nulo si es válida
 */
export const rutValidator: ValidatorFn = (
  control: AbstractControl
): ValidationErrors | null => {
  const rut = control.value;
  if (!rut) {
    return null;
  }
  const dvValid = validaDV(rut);
  const formatValid = /^[0-9]{7,8}-[0-9Kk]{1}$/.test(rut);
  return formatValid ? (dvValid ? null : { rutDv: true }) : { rutFormat: true };
};

En este caso, la función rutValidator valida el formato y el dígito verificador de un RUT. Si el RUT es válido, la función retorna null, si no, retorna un objeto con la validación correspondiente (par clave/true). Esta función se utiliza en el formulario para validar el campo del RUT.

Lectura de JSON

Otra parte importante de este ejemplo es la lectura de un archivo JSON para cargar las regiones y comunas del país. Para esto:

  1. Se debe crear un archivo JSON con la información necesaria. En este caso, se creó el archivo regiones.json en la carpeta public/assets.
  2. Para cargar la información del archivo JSON, se debe crear un servicio de Angular. En este caso, se creó el archivo regiones.service.ts en la carpeta src/app/misc. Este servicio se encarga de cargar la información del archivo JSON y devolverla en un formato adecuado, y para ello utiliza el módulo HttpClient de Angular. Para poder utilizar este módulo, se debe importar el módulo HttpClientModule en el archivo de módulo de la aplicación (app.module.ts).
import { HttpClientModule } from '@angular/common/http';
...

@NgModule({
  declarations: [AppComponent],
  imports: [..., HttpClientModule],
  providers: [...],
  bootstrap: [AppComponent],
})
export class AppModule {}
  1. Una vez obtenidos los datos, se pueden utilizar en el componente de Angular. En este caso, se utilizó el archivo formulario.page.ts para cargar las regiones y comunas del país. Para esto, se utilizó el servicio RegionesService en el constructor del componente, y se llamó al método getRegiones() para obtener la información del archivo JSON.

También se creó la interfaz RegionesJSON para tipar la información del archivo JSON. Esto es importante para que TypeScript pueda inferir los tipos de datos, y para que el código sea más legible. Estas interfaces son propias de este ejemplo, y deben ser creadas según la estructura del archivo JSON. En este caso, se crearon de la siguiente manera:

interface RegionesJSON {
  regiones: {
    [key: string]: {
      nombre: string;
      valor: number;
      comunas: string[];
    };
  };
}

Toda la lógica de la validación, mensajes de error, y carga de regiones y comunas se encuentra en el archivo formulario.page.ts. En este archivo, se utilizan los métodos del servicio RegionesService para cargar la información del archivo JSON, y se utilizan las funciones de validación para validar los campos del formulario.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published