Perché le funzioni di convalida avanzate del modulo

Mentre gli attributi HTML5 forniscono una solida base, spesso cadono breve quando è necessario applicare regole aziendali complesse, fornire feedback in tempo reale, o creare un'esperienza utente fluida attraverso diversi browser. La validazione basata su JavaScript ti dà il pieno controllo su quando e come funziona la validazione, permettendo di implementare regole personalizzate come i misuratori di forza di password, i nomi di campo di pattern-mat

La validazione lato client riduce anche il carico del server e accelera il loop di feedback per gli utenti. Invece di inviare un modulo e in attesa di una risposta del server, gli errori vengono catturati immediatamente. Tuttavia, è fondamentale ricordare che la convalida lato client è un convenienza[, non una misura di sicurezza.

In questa guida, cammineremo attraverso la costruzione di un sistema di validazione avanzato completo utilizzando JavaScript vaniglia. Imparerai a definire regole personalizzate, visualizzare messaggi di errore dinamici, convalidare più campi insieme e mantenere il codice manutenbile.

Comprendere i limiti della convalida HTML5

Gli attributi HTML5 come , , e sono grandi per i semplici controlli, ma non hanno flessibilità.

  • Nessun cross-field validation[[] – Non puoi confermare che una password e un campo di conferma corrispondono solo usando HTML5.
  • Messaggi di errore preferiti[[] – Le tooltips integrate del browser sono inconsistenti tra i browser e non possono essere modellate completamente.
  • Nessun aggiornamento in tempo reale[[] – La convalida HTML5 in genere spara solo su presentazione del modulo, non su ogni tasto di tasti.
  • API di convalida di contrasto[[] – Mentre potente, si basa ancora sulle regole integrate del browser e non ha la capacità di definire facilmente la logica personalizzata complessa.

Con gli ascoltatori degli eventi e le funzioni personalizzate, è possibile creare una validazione sia espressiva che facile da usare.

Impostazione della struttura del modulo HTML

Ecco un esempio che include campi per nome utente, email, password e conferma password. Abbiamo aggiunto attributi per l'accessibilità e vuoto elementi che manterranno messaggi di errore.

<form id="registrationForm" novalidate>
 <div class="form-group">
 <label for="username">Username</label>
 <input type="text" id="username" name="username" placeholder="e.g. johndoe" required>
 <span id="usernameError" class="error-message" role="alert"></span>
 </div>

 <div class="form-group">
 <label for="email">Email address</label>
 <input type="email" id="email" name="email" placeholder="[email protected]" required>
 <span id="emailError" class="error-message" role="alert"></span>
 </div>

 <div class="form-group">
 <label for="password">Password</label>
 <input type="password" id="password" name="password" placeholder="At least 8 characters" required>
 <span id="passwordError" class="error-message" role="alert"></span>
 </div>

 <div class="form-group">
 <label for="confirmPassword">Confirm Password</label>
 <input type="password" id="confirmPassword" name="confirmPassword" placeholder="Repeat password" required>
 <span id="confirmPasswordError" class="error-message" role="alert"></span>
 </div>

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

Si noti l'attributo sul modulo. Questo indica al browser di disattivare la propria validazione integrata in modo da poter gestire tutto con JavaScript. Useremo CSS per mostrare o nascondere messaggi di errore e aggiungere feedback visuali (ad esempio, bordi rossi) a campi non validi.

Progettazione di una logica di convalida centrale

Invece di spargere il codice di validazione tra i gestori degli eventi, creiamo un oggetto centrale che contiene regole personalizzate. Ogni regola è una funzione che restituisce [ (valida) o (invalida) insieme a un messaggio di errore opzionale.

const validators = {
 required: (value) => value.trim() !== '' || 'This field is required.',
 email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || 'Please enter a valid email address.',
 minLength: (min) => (value) => value.length >= min || `Must be at least ${min} characters.`,
 passwordStrength: (value) => {
 const errors = [];
 if (value.length < 8) errors.push('At least 8 characters.');
 if (!/[A-Z]/.test(value)) errors.push('One uppercase letter.');
 if (!/[0-9]/.test(value)) errors.push('One number.');
 if (!/[!@#$%^&*]/.test(value)) errors.push('One special character.');
 return errors.length === 0 || errors.join(' ');
 },
 match: (otherFieldId) => (value, formData) => {
 const otherValue = formData.get(otherFieldId);
 return value === otherValue || 'Passwords do not match.';
 }
};

Si noti che i validatori possono essere parametrizzati – restituisce una funzione che si aspetta il valore. Il validatore [ riceve l'id di un altro campo e utilizza (un oggetto ] per confrontare i valori. Questo modello è altamente riutilizzabile.

Creazione di regole personalizzate per ogni campo

Definire quali validatori si applicano a ciascun campo. Questa mappatura è un oggetto semplice in cui le chiavi sono nomi di campo e valori sono array di funzioni di validatore.

const fieldRules = {
 username: [
 validators.required,
 validators.minLength(3),
 (value) => /^[a-zA-Z0-9_]+$/.test(value) || 'Usernames can only contain letters, numbers, and underscores.'
 ],
 email: [
 validators.required,
 validators.email
 ],
 password: [
 validators.required,
 validators.passwordStrength
 ],
 confirmPassword: [
 validators.required,
 validators.match('password')
 ]
};

Puoi facilmente aggiungere una nuova regola personalizzata, come ad esempio un controllo che il nome utente non è già preso (valida asinc), aggiungendo una funzione asincrona all'elenco.

Validazione in esecuzione su modulo Submission

Collegare un ascoltatore di eventi al modulo che impedisce la presentazione, gestisce tutti i validatori e raccoglie errori. Se non si trovano errori, il modulo è permesso di inviare.

const form = document.getElementById('registrationForm');

form.addEventListener('submit', (event) => {
 event.preventDefault();
 const formData = new FormData(form);
 const errors = validateForm(formData);

 if (Object.keys(errors).length === 0) {
 // All valid – you can submit programmatically or send via fetch
 console.log('Form is valid. Submitting...');
 // form.submit();
 } else {
 displayErrors(errors);
 }
});

La funzione isera su ogni campo, gestisce i suoi validatori e raccoglie messaggi di errore.

function validateForm(formData) {
 const errors = {};
 for (const [fieldName, rules] of Object.entries(fieldRules)) {
 const value = formData.get(fieldName) || '';
 for (const rule of rules) {
 const result = rule(value, formData);
 if (result !== true) {
 errors[fieldName] = result; // result is the error string
 break; // stop after first failure for this field
 }
 }
 }
 return errors;
}

Visualizzazione di Feedback di convalida in tempo reale

Gli utenti beneficiano di vedere gli errori come si digitano, non solo su presentazione. Aggiungi gli ascoltatori degli eventi per e [] su ogni campo. Per evitare gli utenti schiaccianti, un buon modello è quello di convalidare su blur (quando lasciano il campo) e poi ri-validate su ogni input successivo fino a quando l'errore non viene risolto.

document.querySelectorAll('#registrationForm input').forEach((input) => {
 input.addEventListener('blur', () => {
 validateField(input.id, input.value);
 });
 input.addEventListener('input', () => {
 // If the field currently has an error, re-validate on each keystroke
 const errorSpan = document.getElementById(input.id + 'Error');
 if (errorSpan.textContent !== '') {
 validateField(input.id, input.value);
 }
 });
});

La funzione controlla solo le regole per un singolo campo e aggiorna l'intervallo di errore corrispondente.

function validateField(fieldId, value) {
 const formData = new FormData(form);
 formData.set(fieldId, value);
 const rules = fieldRules[fieldId];
 if (!rules) return;
 for (const rule of rules) {
 const result = rule(value, formData);
 if (result !== true) {
 setFieldError(fieldId, result);
 return;
 }
 }
 clearFieldError(fieldId);
}

Errori di dimensionamento e Stati di successo

Usare CSS per modificare l'aspetto visivo dei campi validi/invalidi. Le funzioni e [ aggiungono o rimuovono le classi CSS e aggiornano l'attributo per l'accessibilità.

function setFieldError(fieldId, message) {
 const input = document.getElementById(fieldId);
 const errorSpan = document.getElementById(fieldId + 'Error');
 input.classList.add('is-invalid');
 input.classList.remove('is-valid');
 input.setAttribute('aria-invalid', 'true');
 errorSpan.textContent = message;
}

function clearFieldError(fieldId) {
 const input = document.getElementById(fieldId);
 const errorSpan = document.getElementById(fieldId + 'Error');
 input.classList.remove('is-invalid');
 input.classList.add('is-valid');
 input.setAttribute('aria-invalid', 'false');
 errorSpan.textContent = '';
}

Il corrispondente CSS potrebbe essere:

.is-invalid {
 border-color: #dc3545;
}
.is-valid {
 border-color: #28a745;
}
.error-message {
 color: #dc3545;
 font-size: 0.875rem;
 min-height: 1.2em;
}

Costruire un Meter di Forza password

Un contatore di forza della password fornisce un feedback visivo che incoraggia gli utenti a creare password più forti. Piuttosto che un semplice passaggio / fatica, è possibile calcolare un punteggio e mostrare una barra di progresso.

function passwordStrengthScore(password) {
 let score = 0;
 if (password.length >= 8) score += 1;
 if (password.length >= 12) score += 1;
 if (/[A-Z]/.test(password)) score += 1;
 if (/[a-z]/.test(password)) score += 1;
 if (/[0-9]/.test(password)) score += 1;
 if (/[^A-Za-z0-9]/.test(password)) score += 1;
 return score; // 0-6
}

Attaccare un evento al campo password che aggiorna un elemento metro. È possibile mappare il punteggio ad un'etichetta come Weak (0-2), Fair (3-4), Strong (5-6).

const passwordMeter = document.getElementById('passwordStrengthMeter');
const passwordInput = document.getElementById('password');

passwordInput.addEventListener('input', () => {
 const score = passwordStrengthScore(passwordInput.value);
 const percentage = (score / 6) * 100;
 passwordMeter.value = percentage;
 passwordMeter.style.accentColor = score < 3 ? '#dc3545' : score < 5 ? '#ffc107' : '#28a745';
});

Regole doganali asincroni

Alcuni controlli di validazione richiedono una andata e ritorno al server, come ad esempio il controllo se un nome utente o un'email è già registrato. Per gestire questo senza bloccare l'interfaccia utente, è possibile rendere il convalidatore una funzione asinclinabile e regolare la logica di convalida per attendere il risultato.

const asyncValidators = {
 uniqueUsername: async (value) => {
 try {
 const response = await fetch(`/api/check-username?username=${encodeURIComponent(value)}`);
 const data = await response.json();
 return data.available || 'Username is already taken.';
 } catch {
 return 'Could not verify username availability.';
 }
 }
};

Quindi aggiorna per supportare i validatori asincroni. È inoltre necessario gestire lo stato di caricamento per evitare più richieste simultanee (sotto la richiesta).

Migliori Pratiche per le Forme di Produzione

  • Sempre convalidare lato server[[]. La convalida lato client è una convenienza, mai uno strato di sicurezza.
  • Debounce async check[[]. Se si convalida su tasti per le chiamate server, utilizzare un timer di debounce (ad esempio, 300 ms) per evitare di martellare il server.
  • Utilizza l'API di convalida di configurazione[[] quando possibile. Puoi mescolare JavaScript personalizzato con i metodi integrati e per un approccio ibrido. Questo è utile per i campi che hanno vincoli standard ma hanno bisogno di messaggi personalizzati.
  • Aggiungi la convalida[]. Usa per associare messaggi di errore agli input. Aggiornamento [ e ] regioni in modo che i lettori dello schermo annuncino errori.
  • Test tra browser e dispositivi[[[]]. La gestione di eventi touch, tastiere virtuali e dimensioni dello schermo diverse è essenziale.
  • Tenere a mente le prestazioni[]. Per forme complesse con molti campi, convalida batch o utilizzando [ per gli aggiornamenti dell'interfaccia utente possono impedire il blocco.
  • Provi messaggi di errore chiari e costruttivi[[[]]. Dite all'utente esattamente cosa c'è di sbagliato e come risolverlo. Evitare messaggi generici come "input non valido".

Andare oltre: Convalida modulare con le biblioteche

Se il vostro progetto richiede un alto livello di regole personalizzate e validazione in tempo reale, potreste considerare una libreria leggera come [Validate.js o l' built-in Constraint Validation API. Tuttavia, l'approccio JavaScript vaniglia dimostrato in questo articolo vi dà il pieno controllo e zero dipendenze, che è ideale per le linee guida di performance-

Puoi anche combinare la validazione personalizzata con i quadri moderni come React o Vue, ma i concetti fondamentali di separare le regole dalla presentazione rimangono gli stessi.

Pitfalls comuni da evitare

  • Validare solo su presentazione[]. Gli utenti preferiscono feedback immediato.
  • Non resettare gli errori quando i campi diventano validi[[]. Una volta che un utente risolve un errore, cancellare il messaggio. La logica in tempo reale in questo articolo gestisce automaticamente.
  • .Essumendo l'utente obbedirà alla convalida[]. JavaScript può essere disabilitato interamente.
  • Over-complicare regole[[]. Tenere i validatori semplici e concentrati. Una funzione dovrebbe testare una preoccupazione. Combinarli per applicare più criteri.

Conclusioni

Costruire la validazione di moduli JavaScript personalizzati è un'abilità essenziale per creare applicazioni web lucida e facile da usare. Strutturando il codice intorno alle funzioni di validatore riutilizzabili e feedback in tempo reale, è possibile gestire tutto, dai campi base richiesti ai metri di forza di password complessi e confronti cross-field. Gli esempi forniti in questo articolo ti danno una solida base per adattarsi ai tuoi progetti.

Ricordate che la validazione è parte fondamentale dell'esperienza dell'utente. Controllate attentamente i vostri moduli, ascoltate il feedback degli utenti e abbinate sempre la validazione del lato client con i controlli robusti sul lato server. Per ulteriori informazioni, consultate l'articolo W3C Web Accessibility Initiative guida sulla convalida della forma e l'articolo ]]MDN sulla convalida della forma]]]

Seguendo i modelli e le migliori pratiche qui delineate, creerete forme che sono sia sicure che piacevoli da usare. Iniziate sperimentando i frammenti di codice, personalizzate le regole per abbinare la vostra logica aziendale, e iterate basato sulle interazioni reali dell'utente.