Formular mit Validierung

Ein responsives Kontaktformular mit clientseitiger Validierung und Feedback.

Demo

Code

HTML
CSS
JavaScript
<div class="form-container">
  <form class="form" id="contact-form">
    <div class="form-group">
      <label for="name">Name</label>
      <input type="text" id="name" class="form-control" placeholder="Ihr Name">
      <div class="form-feedback"></div>
    </div>
    
    <div class="form-group">
      <label for="email">E-Mail</label>
      <input type="email" id="email" class="form-control" placeholder="ihre.email@beispiel.de">
      <div class="form-feedback"></div>
    </div>
    
    <div class="form-group">
      <label for="message">Nachricht</label>
      <textarea id="message" class="form-control" rows="5" placeholder="Ihre Nachricht"></textarea>
      <div class="form-feedback"></div>
    </div>
    
    <div class="form-group">
      <button type="submit" class="btn btn-primary">Senden</button>
    </div>
  </form>
</div>
.form-container {
  max-width: 600px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f9f9f9;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

.form {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

label {
  font-weight: 500;
  color: #333;
}

.form-control {
  padding: 12px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 1rem;
  transition: border-color 0.3s, box-shadow 0.3s;
}

.form-control:focus {
  border-color: #4a6cf7;
  box-shadow: 0 0 0 3px rgba(74, 108, 247, 0.2);
  outline: none;
}

.form-control.is-invalid {
  border-color: #dc3545;
}

.form-control.is-valid {
  border-color: #28a745;
}

.form-feedback {
  font-size: 0.85rem;
  min-height: 20px;
}

.invalid-feedback {
  color: #dc3545;
}

.valid-feedback {
  color: #28a745;
}

textarea.form-control {
  resize: vertical;
  min-height: 100px;
}

.btn {
  padding: 12px 24px;
  border: none;
  border-radius: 4px;
  font-size: 1rem;
  font-weight: 500;
  cursor: pointer;
  transition: background-color 0.3s, transform 0.2s;
}

.btn:hover {
  transform: translateY(-2px);
}

.btn:active {
  transform: translateY(0);
}

.btn-primary {
  background-color: #4a6cf7;
  color: white;
}

.btn-primary:hover {
  background-color: #3a5ce4;
}

.form-success-message {
  padding: 15px;
  border-radius: 4px;
  background-color: #d4edda;
  color: #155724;
  margin-bottom: 20px;
  display: none;
}

@media (max-width: 768px) {
  .form-container {
    padding: 15px;
  }
  
  .form-control, .btn {
    padding: 10px;
  }
}
class FormValidator {
  constructor(formId, options = {}) {
    this.form = document.getElementById(formId);
    if (!this.form) return;
    
    this.options = {
      errorClass: options.errorClass || 'is-invalid',
      validClass: options.validClass || 'is-valid',
      errorFeedbackClass: options.errorFeedbackClass || 'invalid-feedback',
      validFeedbackClass: options.validFeedbackClass || 'valid-feedback',
      submitHandler: options.submitHandler || this.defaultSubmitHandler.bind(this)
    };
    
    this.validators = {
      required: (value) => value.trim() !== '' ? true : 'Dieses Feld ist erforderlich',
      email: (value) => {
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        return emailRegex.test(value) ? true : 'Bitte geben Sie eine gültige E-Mail-Adresse ein';
      },
      minLength: (value, length) => value.length >= length ? true : `Mindestens ${length} Zeichen erforderlich`
    };
    
    this.init();
  }
  
  init() {
    this.form.addEventListener('submit', this.handleSubmit.bind(this));
    
    // Optional: Live-Validierung bei Eingabe oder Änderung
    this.form.querySelectorAll('.form-control').forEach(input => {
      input.addEventListener('blur', () => this.validateField(input));
      input.addEventListener('input', () => {
        if (input.classList.contains(this.options.errorClass)) {
          this.validateField(input);
        }
      });
    });
  }
  
  handleSubmit(event) {
    event.preventDefault();
    
    let isValid = true;
    
    // Alle Felder validieren
    this.form.querySelectorAll('.form-control').forEach(input => {
      if (!this.validateField(input)) {
        isValid = false;
      }
    });
    
    if (isValid) {
      this.options.submitHandler(this.form);
    }
  }
  
  validateField(field) {
    // Validierungsregeln aus data-Attributen lesen
    const rules = this.getValidationRules(field);
    
    let isValid = true;
    let errorMessage = '';
    
    // Regeln überprüfen
    for (const rule in rules) {
      if (Object.prototype.hasOwnProperty.call(this.validators, rule)) {
        const result = this.validators[rule](field.value, rules[rule]);
        
        if (result !== true) {
          isValid = false;
          errorMessage = result;
          break;
        }
      }
    }
    
    // Feedback anzeigen
    this.showFeedback(field, isValid, errorMessage);
    
    return isValid;
  }
  
  getValidationRules(field) {
    const rules = {};
    
    // Validierungsregeln basierend auf Feldtyp und ID
    if (field.id === 'name') {
      rules.required = true;
      rules.minLength = 2;
    } else if (field.id === 'email') {
      rules.required = true;
      rules.email = true;
    } else if (field.id === 'message') {
      rules.required = true;
      rules.minLength = 10;
    }
    
    return rules;
  }
  
  showFeedback(field, isValid, message = '') {
    const feedbackElement = field.nextElementSibling;
    if (!feedbackElement || !feedbackElement.classList.contains('form-feedback')) return;
    
    // CSS-Klassen und Feedback-Text aktualisieren
    field.classList.remove(this.options.errorClass, this.options.validClass);
    feedbackElement.classList.remove(this.options.errorFeedbackClass, this.options.validFeedbackClass);
    
    if (field.value) { // Nur Feedback anzeigen, wenn ein Wert eingegeben wurde
      if (isValid) {
        field.classList.add(this.options.validClass);
        feedbackElement.classList.add(this.options.validFeedbackClass);
        feedbackElement.textContent = '';
      } else {
        field.classList.add(this.options.errorClass);
        feedbackElement.classList.add(this.options.errorFeedbackClass);
        feedbackElement.textContent = message;
      }
    } else {
      feedbackElement.textContent = '';
    }
  }
  
  defaultSubmitHandler(form) {
    // Formular-Daten sammeln
    const formData = new FormData(form);
    const data = {};
    for (const [key, value] of formData.entries()) {
      data[key] = value;
    }
    
    // Hier würde normalerweise ein AJAX-Request stehen
    console.log('Formular erfolgreich abgesendet', data);
    
    // Erfolgsmeldung anzeigen
    let successMessage = document.querySelector('.form-success-message');
    if (!successMessage) {
      successMessage = document.createElement('div');
      successMessage.className = 'form-success-message';
      successMessage.textContent = 'Vielen Dank für Ihre Nachricht! Wir werden uns so schnell wie möglich bei Ihnen melden.';
      form.parentNode.insertBefore(successMessage, form);
    }
    
    successMessage.style.display = 'block';
    form.reset();
    
    // Validierungsmarkierungen zurücksetzen
    form.querySelectorAll('.form-control').forEach(input => {
      input.classList.remove(this.options.errorClass, this.options.validClass);
      const feedbackElement = input.nextElementSibling;
      if (feedbackElement && feedbackElement.classList.contains('form-feedback')) {
        feedbackElement.textContent = '';
        feedbackElement.classList.remove(this.options.errorFeedbackClass, this.options.validFeedbackClass);
      }
    });
  }
}

document.addEventListener('DOMContentLoaded', function() {
  const contactFormValidator = new FormValidator('contact-form');
});

Erklärung

Dieses Formular mit clientseitiger Validierung bietet eine hervorragende Benutzererfahrung durch sofortiges Feedback ohne Seitenneuladen:

  • Umfassende Validierungsregeln für verschiedene Feldtypen (Text, E-Mail, etc.)
  • Farbliche Hervorhebung der Felder (rot für ungültige, grün für gültige Eingaben)
  • Spezifische Fehlermeldungen für unterschiedliche Validierungsfehler
  • Live-Validierung während der Eingabe für sofortiges Feedback
  • Einfache Anpassbarkeit und Erweiterbarkeit durch die Klassenstruktur

Die JavaScript-Klasse FormValidator bietet eine modulare Lösung, die leicht auf verschiedene Formulare angewendet werden kann. Die Validierungslogik ist von der UI-Logik getrennt, was die Wartbarkeit erhöht.

Verwendung

Dieses validierte Formular eignet sich perfekt für Kontaktformulare, Anmeldeformulare, Bestellformulare oder Umfragen. Die clientseitige Validierung verbessert die Benutzererfahrung, indem sie sofortiges Feedback gibt, und reduziert ungültige Formulareinsendungen.