Huemul, ícono de devsChile

Chucao — formularios

Los controles de formulario de Chucao participan en el <form> nativo: su valor llega a FormData y al submit, y validan como controles nativos.

Cómo funcionan los formularios

Los seis controles de formulario — ch-checkbox, ch-input, ch-radio, ch-select, ch-switch y ch-textarea — son form-associated custom elements. Dentro de un <form> se comportan como controles nativos, sin JavaScript de por medio:

Es un cambio de comportamiento: en versiones anteriores estos controles no participaban en el formulario. Si compensabas esa ausencia a mano (por ejemplo, con hidden inputs alimentando FormData), hay que quitar ese trabajo manual para no duplicar valores.

Lo mínimo

Un formulario con un solo campo, leído con JavaScript puro:

<form id="contacto">
  <ch-input name="email" label="Correo" type="email" required></ch-input>
  <ch-button id="enviar">Enviar</ch-button>
</form>
const form = document.getElementById('contacto');
const submit = document.getElementById('enviar');

// ch-button no puede disparar el submit por sí solo (vive en su shadow
// root): conecta chClick con requestSubmit(), que valida y dispara submit.
submit.addEventListener('chClick', () => form.requestSubmit());

form.addEventListener('submit', (event) => {
  event.preventDefault(); // sin backend real, acá solo leemos los datos
  const data = Object.fromEntries(new FormData(form));
  console.log(data); // { email: 'tu@email.com' }
});

Ejemplo: formulario de login

Correo y contraseña con required. El navegador valida antes de disparar submit: si un campo obligatorio está vacío, muestra el mensaje y no se llega al handler.

Entrar

        

HTML

<form id="login-form">
  <ch-input name="email" label="Correo electrónico" type="email" required error-message="Ingresa un correo válido"></ch-input>
  <ch-input name="password" label="Contraseña" type="password" required error-message="Ingresa tu contraseña"></ch-input>
  <ch-button id="login-submit">Entrar</ch-button>
</form>

JavaScript

const form = document.getElementById('login-form');
const output = document.getElementById('login-result');
const submit = document.getElementById('login-submit');

// ch-button no puede disparar el submit por sí solo: conecta chClick con
// requestSubmit(), que valida y dispara `submit` si el formulario es válido.
submit.addEventListener('chClick', () => form.requestSubmit());

form.addEventListener('submit', (event) => {
  event.preventDefault(); // en este demo no hay backend
  const data = Object.fromEntries(new FormData(form));

  // fetch('/api/login', { method: 'POST', body: JSON.stringify(data) })

  output.textContent = JSON.stringify(data, null, 2);
});

Ejemplo: suscripción a un newsletter

Un correo y un checkbox de consentimiento required. Como con un checkbox nativo, consent solo aparece en FormData cuando está marcado.

Suscribirme

        

HTML

<form id="newsletter-form">
  <ch-input name="email" label="Correo electrónico" type="email" required error-message="Ingresa un correo válido"></ch-input>
  <ch-checkbox name="consent" label="Acepto recibir novedades por correo" required error-message="Necesitamos tu consentimiento"></ch-checkbox>
  <ch-button id="newsletter-submit">Suscribirme</ch-button>
</form>

JavaScript

const form = document.getElementById('newsletter-form');
const output = document.getElementById('newsletter-result');
const submit = document.getElementById('newsletter-submit');

submit.addEventListener('chClick', () => form.requestSubmit());

form.addEventListener('submit', (event) => {
  event.preventDefault();

  // Si el checkbox está sin marcar, `consent` no aparece en FormData.
  const data = Object.fromEntries(new FormData(form));

  if (data.consent !== 'on') {
    // el usuario no dio consentimiento: no suscribir
    return;
  }

  // fetch('/api/newsletter', { method: 'POST', body: JSON.stringify(data) })

  output.textContent = JSON.stringify(data, null, 2);
});

Notas