CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sweetalert2

A beautiful, responsive, customizable and accessible replacement for JavaScript's popup boxes

Pending
Overview
Eval results
Files

input-validation.mddocs/

Input Handling and Validation

Comprehensive input support including various input types, validation, and input state management for creating interactive forms within popups.

Capabilities

Input Element Access

Methods to access and control input elements within popups.

/**
 * Gets the input DOM node, works with input parameter
 * @returns The input element or null if no input is present
 */
function getInput(): HTMLInputElement | null;

/**
 * Disables the popup input. A disabled input element is unusable and un-clickable
 */
function disableInput(): void;

/**
 * Enables the popup input
 */
function enableInput(): void;

Usage Examples:

// Access and modify input
Swal.fire({
  title: 'Enter your name',
  input: 'text',
  didOpen: () => {
    const input = Swal.getInput();
    if (input) {
      input.style.border = '2px solid #007bff';
      input.addEventListener('focus', () => {
        input.style.borderColor = '#28a745';
      });
    }
  }
});

// Conditional input enabling
Swal.fire({
  title: 'Account Setup',
  html: `
    <label>
      <input type="checkbox" id="terms-checkbox"> I accept the terms
    </label>
  `,
  input: 'text',
  inputPlaceholder: 'Enter username',
  didOpen: () => {
    Swal.disableInput();
    
    const checkbox = document.getElementById('terms-checkbox');
    checkbox.addEventListener('change', (e) => {
      if (e.target.checked) {
        Swal.enableInput();
      } else {
        Swal.disableInput();
      }
    });
  }
});

Validation Messages

Methods to display and manage validation feedback.

/**
 * Shows a validation message
 * @param validationMessage - The validation message text to display
 */
function showValidationMessage(validationMessage: string): void;

/**
 * Hides validation message
 */
function resetValidationMessage(): void;

/**
 * Gets the validation message container
 * @returns The validation message element or null if not present
 */
function getValidationMessage(): HTMLElement | null;

Usage Examples:

// Real-time validation
Swal.fire({
  title: 'Email Validation',
  input: 'email',
  inputPlaceholder: 'Enter your email',
  didOpen: () => {
    const input = Swal.getInput();
    if (input) {
      input.addEventListener('input', (e) => {
        const email = e.target.value;
        const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        
        if (email && !emailRegex.test(email)) {
          Swal.showValidationMessage('Please enter a valid email address');
        } else {
          Swal.resetValidationMessage();
        }
      });
    }
  }
});

// Custom validation message styling
Swal.fire({
  title: 'Password',
  input: 'password',
  inputValidator: (value) => {
    if (!value) {
      return 'Password is required';
    }
    if (value.length < 8) {
      return 'Password must be at least 8 characters';
    }
  },
  didOpen: () => {
    const validationMsg = Swal.getValidationMessage();
    if (validationMsg) {
      validationMsg.style.fontSize = '14px';
      validationMsg.style.fontWeight = 'bold';
    }
  }
});

Input Types and Configuration

SweetAlert2 supports various input types through the input option in SweetAlertOptions.

type SweetAlertInput = 
  | 'text'           // Text input
  | 'email'          // Email input with validation
  | 'password'       // Password input (masked)
  | 'number'         // Numeric input
  | 'tel'            // Telephone input
  | 'search'         // Search input
  | 'range'          // Range slider
  | 'textarea'       // Multi-line text area
  | 'select'         // Dropdown select
  | 'radio'          // Radio button group
  | 'checkbox'       // Checkbox input
  | 'file'           // File upload
  | 'url'            // URL input with validation
  | 'date'           // Date picker
  | 'datetime-local' // Date and time picker
  | 'time'           // Time picker
  | 'week'           // Week picker
  | 'month';         // Month picker

Text-based Inputs

// Text input with validation
const { value: username } = await Swal.fire({
  title: 'Enter username',
  input: 'text',
  inputLabel: 'Username',
  inputPlaceholder: 'Your username',
  inputAttributes: {
    'maxlength': '20',
    'autocomplete': 'username'
  },
  inputValidator: (value) => {
    if (!value) {
      return 'Username is required!';
    }
    if (value.length < 3) {
      return 'Username must be at least 3 characters!';
    }
    if (!/^[a-zA-Z0-9_]+$/.test(value)) {
      return 'Username can only contain letters, numbers, and underscores!';
    }
  }
});

// Email input
const { value: email } = await Swal.fire({
  title: 'Email address',
  input: 'email',
  inputLabel: 'Your email address',
  inputPlaceholder: 'user@example.com',
  validationMessage: 'Please enter a valid email address'
});

// Password input
const { value: password } = await Swal.fire({
  title: 'Enter password',
  input: 'password',
  inputLabel: 'Password',
  inputPlaceholder: 'Your password',
  inputValidator: (value) => {
    if (!value) return 'Password is required';
    if (value.length < 8) return 'Password must be at least 8 characters';
    if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
      return 'Password must contain uppercase, lowercase, and number';
    }
  }
});

// Textarea
const { value: message } = await Swal.fire({
  title: 'Your message',
  input: 'textarea',
  inputLabel: 'Message',
  inputPlaceholder: 'Type your message here...',
  inputAttributes: {
    'rows': '5',
    'maxlength': '500'
  }
});

Selection Inputs

// Select dropdown
const { value: country } = await Swal.fire({
  title: 'Select your country',
  input: 'select',
  inputOptions: {
    'US': 'United States',
    'CA': 'Canada',
    'UK': 'United Kingdom',
    'DE': 'Germany',
    'FR': 'France'
  },
  inputPlaceholder: 'Choose a country',
  inputValidator: (value) => {
    if (!value) {
      return 'Please select a country!';
    }
  }
});

// Radio buttons
const { value: size } = await Swal.fire({
  title: 'Select size',
  input: 'radio',
  inputOptions: {
    'small': 'Small',
    'medium': 'Medium',
    'large': 'Large',
    'xlarge': 'Extra Large'
  },
  inputValidator: (value) => {
    if (!value) {
      return 'Please select a size!';
    }
  }
});

// Checkbox
const { value: agreement } = await Swal.fire({
  title: 'Terms and Conditions',
  input: 'checkbox',
  inputValue: 0,
  inputPlaceholder: 'I agree to the terms and conditions',
  inputValidator: (value) => {
    if (!value) {
      return 'You must accept the terms and conditions!';
    }
  }
});

Date and Time Inputs

// Date picker
const { value: birthDate } = await Swal.fire({
  title: 'Birth date',
  input: 'date',
  inputLabel: 'When were you born?',
  inputAttributes: {
    'min': '1900-01-01',
    'max': new Date().toISOString().split('T')[0]
  },
  inputValidator: (value) => {
    if (!value) return 'Please select your birth date';
    const date = new Date(value);
    const today = new Date();
    if (date > today) return 'Birth date cannot be in the future';
  }
});

// Time picker
const { value: meetingTime } = await Swal.fire({
  title: 'Meeting time',
  input: 'time',
  inputLabel: 'Select meeting time',
  inputValue: '09:00',
  inputAttributes: {
    'min': '08:00',
    'max': '18:00'
  }
});

// DateTime local
const { value: appointment } = await Swal.fire({
  title: 'Schedule appointment',
  input: 'datetime-local',
  inputLabel: 'Appointment date and time',
  inputAttributes: {
    'min': new Date().toISOString().slice(0, 16)
  }
});

File Input

// File upload
const { value: file } = await Swal.fire({
  title: 'Upload file',
  input: 'file',
  inputLabel: 'Select a file to upload',
  inputAttributes: {
    'accept': 'image/*,.pdf,.doc,.docx',
    'multiple': false
  },
  inputValidator: (file) => {
    if (!file) {
      return 'Please select a file!';
    }
    if (file.size > 10 * 1024 * 1024) { // 10MB
      return 'File size must be less than 10MB!';
    }
  }
});

if (file) {
  console.log('Selected file:', file.name, file.size, 'bytes');
}

Range Input

// Range slider
const { value: volume } = await Swal.fire({
  title: 'Set volume',
  input: 'range',
  inputLabel: 'Volume level',
  inputAttributes: {
    'min': '0',
    'max': '100',
    'step': '5'
  },
  inputValue: 50,
  didOpen: () => {
    const input = Swal.getInput();
    const output = document.createElement('output');
    output.style.display = 'block';
    output.style.marginTop = '10px';
    output.style.fontSize = '18px';
    output.style.fontWeight = 'bold';
    output.textContent = input.value + '%';
    
    input.parentNode.appendChild(output);
    
    input.addEventListener('input', (e) => {
      output.textContent = e.target.value + '%';
    });
  }
});

Advanced Input Validation

// Multi-field validation
const result = await Swal.fire({
  title: 'Registration Form',
  html: `
    <input id="reg-username" class="swal2-input" placeholder="Username" maxlength="20">
    <input id="reg-email" class="swal2-input" type="email" placeholder="Email">
    <input id="reg-password" class="swal2-input" type="password" placeholder="Password">
    <input id="reg-confirm" class="swal2-input" type="password" placeholder="Confirm Password">
  `,
  focusConfirm: false,
  showCancelButton: true,
  confirmButtonText: 'Register',
  preConfirm: () => {
    const username = document.getElementById('reg-username').value;
    const email = document.getElementById('reg-email').value;
    const password = document.getElementById('reg-password').value;
    const confirm = document.getElementById('reg-confirm').value;
    
    // Validation
    if (!username) {
      Swal.showValidationMessage('Username is required');
      return false;
    }
    if (username.length < 3) {
      Swal.showValidationMessage('Username must be at least 3 characters');
      return false;
    }
    if (!email) {
      Swal.showValidationMessage('Email is required');
      return false;
    }
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
      Swal.showValidationMessage('Please enter a valid email');
      return false;
    }
    if (!password) {
      Swal.showValidationMessage('Password is required');
      return false;
    }
    if (password.length < 8) {
      Swal.showValidationMessage('Password must be at least 8 characters');
      return false;
    }
    if (password !== confirm) {
      Swal.showValidationMessage('Passwords do not match');
      return false;
    }
    
    return { username, email, password };
  }
});

if (result.isConfirmed) {
  console.log('Registration data:', result.value);
}

// Async validation
const { value: apiKey } = await Swal.fire({
  title: 'API Key Validation',
  input: 'text',
  inputLabel: 'Enter your API key',
  inputPlaceholder: 'sk-...',
  showLoaderOnConfirm: true,
  preConfirm: async (apiKey) => {
    try {
      // Simulate API validation
      const response = await fetch('/api/validate-key', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ key: apiKey })
      });
      
      if (!response.ok) {
        throw new Error('Invalid API key');
      }
      
      return apiKey;
    } catch (error) {
      Swal.showValidationMessage(`Validation failed: ${error.message}`);
      return false;
    }
  }
});

Input Configuration Options

All input-related options available in SweetAlertOptions:

interface InputOptions {
  input?: SweetAlertInput;
  inputValue?: SyncOrAsync<string | number | File | FileList> | null;
  inputPlaceholder?: string;
  inputLabel?: string;
  inputOptions?: SyncOrAsync<ReadonlyMap<string, string> | Record<string, any>>;
  inputAutoTrim?: boolean;
  inputAutoFocus?: boolean;
  inputAttributes?: Record<string, string>;
  inputValidator?: (value: any) => SyncOrAsync<string | null | false | void>;
  validationMessage?: string;
  returnInputValueOnDeny?: boolean;
}

Install with Tessl CLI

npx tessl i tessl/npm-sweetalert2

docs

dialog-management.md

dom-access.md

index.md

input-validation.md

state-management.md

timer-control.md

tile.json