Formulaires et mutations

EmberKit fournit une gestion de formulaires intégrée avec validation, état et soumission.

Formulaire de base

import { createSignal } from '@emberkit/core';
import { handleFormSubmit } from '@emberkit/core';

function ContactForm() {
  const [submitted, setSubmitted] = createSignal(false);

  async function onSubmit(event: SubmitEvent) {
    await handleFormSubmit(event, {
      onSubmit: async (formData) => {
        await fetch('/api/contact', {
          method: 'POST',
          body: formData,
        });
        setSubmitted(true);
      },
      onError: (errors) => {
        console.error('Validation failed:', errors);
      },
    });
  }

  if (submitted()) {
    return <div className="alert-success">Message sent!</div>;
  }

  return (
    <form onSubmit={onSubmit}>
      <input name="name" placeholder="Name" required />
      <input name="email" type="email" placeholder="Email" required />
      <textarea name="message" placeholder="Message" required />
      <button type="submit">Send</button>
    </form>
  );
}

Validation

Définissez un schéma de validation :

import { createFormValidator } from '@emberkit/core';

const validator = createFormValidator({
  fields: {
    name: {
      required: true,
      minLength: 2,
      maxLength: 50,
    },
    email: {
      required: true,
      pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
    },
    age: {
      custom: (value) => {
        const n = Number(value);
        if (n < 18) return 'Must be at least 18';
        if (n > 120) return 'Invalid age';
        return null;
      },
    },
  },
});

const errors = validator.validate({ name: '', email: 'bad', age: 15 });
// { name: 'name is required', email: 'email is invalid', age: 'Must be at least 18' }

Validateurs intégrés

Nom du champValidation
emailCorrespondance de motif pour format email
urlCorrespondance de motif pour URLs HTTP(S)
phoneCorrespondance de motif pour numéros de téléphone

État du formulaire

Suivez l'état manuellement pour les formulaires complexes :

import { createSignal, createFormState, setFieldValue, setFieldError } from '@emberkit/core';

function SignupForm() {
  const [state, setState] = createSignal(createFormState({
    username: '',
    password: '',
  }));

  function handleChange(name: string, value: string) {
    setState(prev => setFieldValue(prev, name, value));
  }

  return (
    <form>
      <input
        value={state().values.username}
        onChange={(e) => handleChange('username', e.target.value)}
      />
      {state().errors.username && <span>{state().errors.username}</span>}
    </form>
  );
}

Mutations

Les mutations côté serveur gèrent les changements de données :

// src/routes/_api/posts.ts
export async function POST(request: Request) {
  const data = await request.json();
  
  // Validate
  if (!data.title || !data.content) {
    return new Response('Missing fields', { status: 400 });
  }

  // Save to database
  const post = await db.posts.create(data);
  
  return new Response(JSON.stringify(post), {
    headers: { 'Content-Type': 'application/json' },
  });
}

Amélioration progressive

<form action="/api/contact" method="POST">
  <input name="name" />
  <input name="email" type="email" />
  <button type="submit">Send</button>
</form>

Avec JavaScript chargé, la validation côté client s'exécute d'abord, puis la mutation est gérée via fetch.

Prochaines étapes

  • Signals — Gestion d'état des formulaires
  • Routing — Routes API pour mutations
  • SSR — Gestion de formulaires côté serveur