search results:

    • Standard
    • React
    Pricing Learn Community
    • + D
    • Light
    • Dark
    • System
    logo TW Elements
    • Getting started
      • Quick start
      • Tutorials
      • Design system
      • Local installation
      • Optimization
      • Dark mode
      • Theming
      • Changelog
      • Migrating to v2
      • Internationalization guide
      • Class customization
      • Icons Integration
    • CommercialNew
      • Pricing
      • License
      • Installation
      • Git & repository
      • Premium Support
    • Integrations
      • Angular
      • ASP.NET
      • Django
      • Express
      • Laravel
      • Next
      • Nuxt
      • Qwik
      • React
      • Remix
      • Solid
      • Svelte
      • SvelteKit
      • Vue
    • Content & styles
      • Animations
      • Animations Extended
      • Colors
      • Dividers
      • Figures
      • Headings
      • Hover effects
      • Icons
      • Images
      • Mask
      • Shadows
      • Typography
    • Navigation
      • Breadcrumbs
      • Footer
      • Headers
      • Mega menu
      • Navbar
      • Offcanvas
      • Pagination
      • Pills
      • Scrollspy
      • Sidenav
      • Tabs
    • Components
      • Accordion
      • Alerts
      • Avatar
      • Badges
      • Button group
      • Buttons
      • Cards
      • Carousel
      • Chips
      • Collapse
      • Dropdown
      • Gallery
      • Jumbotron
      • Lightbox
      • Link
      • List group
      • Modal
      • Notifications
      • Paragraphs
      • Placeholders
      • Popconfirm
      • Popover
      • Progress
      • Rating
      • Scroll back to top button
      • Social buttons
      • Spinners
      • Stepper
      • Testimonials
      • Timeline
      • Toast
      • Tooltip
      • Video
      • Video carousel
    • Forms
      • Autocomplete
      • Checkbox
      • Datepicker
      • Datetimepicker
      • File input
      • Form templates
      • Input Group
      • Inputs
      • Login form
      • Multi range slider
      • Radio
      • Range
      • Registration form
      • Search
      • Select
      • Switch
      • Textarea
      • Timepicker
      • Validation
    • Data
      • Charts
      • Charts advanced
      • Datatables
      • Tables
    • Methods
      • Clipboard
      • Infinite scroll
      • Lazy loading
      • Loading management
      • Ripple
      • Scrollbar
      • Smooth scroll
      • Sticky
      • Touch
    • Design Blocks
      • Admin Charts
      • Admin Complex
      • Admin Forms
      • Admin Maps
      • Admin Navigation
      • Admin tables
      • Banners
      • Contact
      • Content
      • CTA
      • FAQ
      • Features
      • Headers
      • Hero / Intro sections
      • Logo clouds
      • Mega menu
      • News
      • Newsletter
      • Pricing
      • Projects
      • Stats
      • Stats admin
      • Team
      • Testimonials
    • Tools
      • Button generator
      • Card generator
      • Flexbox generator
      • Footer generator
      • Form builder
      • Grid generator
      • Icon generator
      • Instagram Filters generator
      • Logo generator
      • Table generator
      • Typography generator
    • Coming Soon
      • Angular
      • Builder
      • Templates
      • Vue
    • Resources
      • Playground
      • YouTube Channel
      • Private FB Group
      • Newsletter
      • UI Design course New
      • UI / UX tips
    • Overview
    • API

    Validation

    Tailwind CSS Validation

    Validate TW elements components with ease. Validation is a simple and lightweight component that adds validation to your forms.

    Required ES init: Validation *
    * UMD autoinits are enabled by default. This means that you don't need to initialize the component manually. However if you are using TW Elements ES format then you should pass the required components to the initTWE method.

    Basic example

    TW elements Validation allows you to show the result of you validation in a simple and elegant way. You can use just the styling that Validation component provides or you can add rules and messages for each input. Validation component is fully customizable.

    If you want to control the validation yourself and only use the styling, add data-twe-validated="true" to the form and data-twe-validation-state="valid/invalid" to the element if it's value is valid.

    To initialize the component use data-twe-validation-init attribute and add data-twe-validate="input" to the wrapper of element you want the styles to be applied to.

    Inside the data-twe-validate attribute you can provide

    • input - for TW Elements input components
    • basic - for native inputs
    • checkbox - for checkboxes and switches
    • radio - radio component
    • HTML
    • javascript
    • umd
            
                
          <form id="form-1" data-twe-validation-init>
            <div
              class="relative mb-3"
              id="input-1"
              data-twe-input-wrapper-init
              data-twe-validate="input">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormControlInput1"
                placeholder="Example label" />
              <label
                for="exampleFormControlInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              id="validation-1"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
              Validate
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input });
    
          const validation1 = document.getElementById("validation-1");
          const form1 = document.getElementById("form-1");
          const input1 = document.getElementById("input-1");
          let valid = true;
          validation1.addEventListener("click", (e) => {
            e.preventDefault();
            input1.setAttribute(
              "data-twe-validation-state",
              valid ? "valid" : "invalid"
            );
            form1.setAttribute("data-twe-validated", true);
            valid = !valid;
          });
          
            
        
            
                
          const validation1 = document.getElementById("validation-1");
          const form1 = document.getElementById("form-1");
          const input1 = document.getElementById("input-1");
          let valid = true;
          validation1.addEventListener("click", (e) => {
            e.preventDefault();
            input1.setAttribute(
              "data-twe-validation-state",
              valid ? "valid" : "invalid"
            );
            form1.setAttribute("data-twe-validated", true);
            valid = !valid;
          });
          
            
        

    Hey there 👋 we're excited about TW elements and want to see it grow! If you enjoy it, help the project grow by sharing it with your peers. Every share counts, thank you!

    Advanced Example

    Add data-twe-validation-ruleset attribute with a | separated list of validation rules to make the component check them for you. Add data-twe-submit-btn-ref to the submit button so that you don't have to listen on the button clicks yourself.

    Click the Validate button to validate the form again.

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormAdvancedInput1"
                placeholder="Example label" />
              <label
                for="exampleFormAdvancedInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input });
          
            
        

    Existing validation rules

    In TW elements validation we have already provided few rules that can be used to check the value of inputs. You can extend the list with use of customRules and customErrorMessages options. Example on how to do this can be found in section Custom Validation

    • isRequired - checks if any value was set
    • isEmail - checks for valid email address
    • isLongerThan - checks if string is longer than (n) length
    • isShorterThan - checks if string is shorter than (n) length
    • isChecked - checks if value was checked
    • isPhone - checks if the value has length equal to 9
    • isNumber - checks if value is type number
    • isString - checks if value is type string
    • isBoolean - checks if value is type boolean
    • isDate - checks if value is a date in format DD/MM/YYYY
    • is12hFormat - checks if value is time in 12h format
    • is24hFormat - checks if value is time in 24h format

    Supported components

    The Validation component supports:

    Select

    Used rules: isRequired

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div data-twe-validate="input" data-twe-validation-ruleset="isRequired">
              <select data-twe-select-init data-twe-select-clear-button="true">
                <option value="" hidden selected></option>
                <option value="1">One</option>
                <option value="2">Two</option>
                <option value="3">Three</option>
                <option value="4">Four</option>
                <option value="5">Five</option>
                <option value="6">Six</option>
                <option value="7">Seven</option>
                <option value="8">Eight</option>
              </select>
              <label data-twe-select-label-ref>Example label</label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Select,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Select });
          
            
        

    Datepicker

    Used rules: isRequired, isDate

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative mb-3"
              data-twe-datepicker-init
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isDate">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Select a date" />
              <label
                for="floatingInput"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Select a date</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Datepicker,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Datepicker, Input });
          
            
        

    Timepicker

    Used rules: isRequired, is12hFormat

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative mb-3"
              data-twe-timepicker-init
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|is12hFormat">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="form1" />
              <label
                for="form1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Select a time</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Timepicker,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Timepicker, Input });
          
            
        

    Input Group

    With default input. Used rules: isRequired

    @
    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div class="relative flex flex-nowrap items-start">
              <span
                class="flex items-center whitespace-nowrap rounded-s border border-e-0 border-solid border-neutral-200 px-3 py-[0.25rem] text-center text-base font-normal leading-[1.6] text-surface dark:border-white/10 dark:text-white"
                id="addon-wrapping"
                >@</span
              >
              <div
                class="relative inline-block w-full"
                data-twe-validate="basic"
                data-twe-validation-ruleset="isRequired">
                <input
                  type="text"
                  class="relative m-0 block w-full flex-auto rounded-e border border-solid border-neutral-200 bg-transparent bg-clip-padding px-3 py-[0.25rem] text-base font-normal leading-[1.6] text-surface outline-none transition duration-200 ease-in-out placeholder:text-neutral-500 focus:z-[3] focus:border-primary focus:shadow-inset focus:outline-none motion-reduce:transition-none dark:border-white/10 dark:text-white dark:placeholder:text-neutral-200 dark:autofill:shadow-autofill dark:focus:border-primary"
                  placeholder="Username"
                  aria-label="Username"
                  aria-describedby="addon-wrapping" />
              </div>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation });
          
            
        

    With TE Input. Used rules: isRequired

    @
    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative mb-4 flex items-stretch"
              data-twe-input-wrapper-init
              data-twe-input-group-ref
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired">
              <span
                class="flex items-center whitespace-nowrap border-e border-solid border-secondary-500 px-3 py-[0.25rem] text-center text-base font-normal leading-[1.6] text-surface dark:border-neutral-400 dark:text-white"
                id="basic-addon1"
                data-twe-input-group-text-ref
                >@</span
              >
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Username"
                aria-label="Username"
                id="exampleFormControlInput"
                aria-describedby="basic-addon1" />
              <label
                for="exampleFormControlInput"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input });
          
            
        

    Textarea

    Used rules: isRequired

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative mb-4 flex items-stretch"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired">
              <textarea
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormControlTextarea1"
                rows="3"
                placeholder="Your message"></textarea>
              <label
                for="exampleFormControlTextarea1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example textarea</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input });
          
            
        

    Checkbox

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative block min-h-[1.5rem] ps-[1.5rem]"
              data-twe-validate="checkbox"
              data-twe-validation-ruleset="isChecked">
              <input
                class="relative float-left -ms-[1.5rem] me-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-secondary-500 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-checkbox before:shadow-transparent before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ms-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-black/60 focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-black/60 focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-checkbox checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ms-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent rtl:float-right dark:border-neutral-400 dark:checked:border-primary dark:checked:bg-primary"
                type="checkbox"
                value=""
                id="checkboxChecked"
                checked />
              <label
                class="inline-block ps-[0.15rem] hover:cursor-pointer"
                for="checkboxChecked">
                Checked checkbox
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation });
          
            
        

    Switch

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative block min-h-[1.5rem]"
              data-twe-validate="checkbox"
              data-twe-validation-ruleset="isChecked">
              <input
                class="me-2 mt-[0.3rem] h-3.5 w-8 appearance-none rounded-[0.4375rem] bg-black/25 before:pointer-events-none before:absolute before:h-3.5 before:w-3.5 before:rounded-full before:bg-transparent before:content-[''] after:absolute after:z-[2] after:-mt-[0.1875rem] after:h-5 after:w-5 after:rounded-full after:border-none after:bg-white after:shadow-switch-2 after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:bg-primary checked:after:absolute checked:after:z-[2] checked:after:-mt-[3px] checked:after:ms-[1.0625rem] checked:after:h-5 checked:after:w-5 checked:after:rounded-full checked:after:border-none checked:after:bg-primary checked:after:shadow-switch-1 checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer focus:outline-none focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-switch-3 focus:before:shadow-black/60 focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-5 focus:after:w-5 focus:after:rounded-full focus:after:content-[''] checked:focus:border-primary checked:focus:bg-primary checked:focus:before:ms-[1.0625rem] checked:focus:before:scale-100 checked:focus:before:shadow-switch-3 checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] dark:bg-white/25 dark:after:bg-surface-dark dark:checked:bg-primary dark:checked:after:bg-primary"
                type="checkbox"
                role="switch"
                id="flexSwitchCheckDefault" />
              <label
                class="inline-block ps-[0.15rem] hover:cursor-pointer"
                for="flexSwitchCheckDefault"
                >Default switch checkbox input</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation });
          
            
        

    Radio

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-twe-validation-init>
            <div
              class="relative block min-h-[1.5rem] ps-[1.5rem]"
              data-twe-validate="radio"
              data-twe-validation-ruleset="isChecked">
              <input
                class="relative float-left -ms-[1.5rem] me-1 mt-0.5 h-5 w-5 appearance-none rounded-full border-2 border-solid border-secondary-500 before:pointer-events-none before:absolute before:h-4 before:w-4 before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-checkbox before:shadow-transparent before:content-[''] after:absolute after:z-[1] after:block after:h-4 after:w-4 after:rounded-full after:content-[''] checked:border-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-primary checked:after:bg-primary checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-black/60 focus:shadow-none focus:outline-none focus:ring-0 focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-black/60 focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:border-primary checked:focus:before:scale-100 checked:focus:before:shadow-checkbox checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] rtl:float-right dark:border-neutral-400 dark:checked:border-primary"
                type="radio"
                name="flexRadioDefault"
                id="radioDefault01" />
              <label
                class="mt-px inline-block ps-[0.15rem] hover:cursor-pointer"
                for="radioDefault01">
                Default radio
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation });
          
            
        

    Active validation

    Add data-twe-active-validation="true" to make the validation listen to the input changes.

    • HTML
    • javascript
            
                
          <form
            data-twe-validation-init
            data-twe-active-validation="true"
            autocomplete="off">
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isNumber|isLongerThan(2)|isShorterThan(6)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleActive1"
                placeholder="Example label" />
              <label
                for="exampleActive1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input });
          
            
        

    Custom validation

    You can add custom rules to the validation. Simply add a new method to the customRules option and add customErrorMessages for that method. You can also add a callback to the validation so that the Validation component will call it after the validation is done. Check the inspect tools to see how it works.

    • HTML
    • javascript
    • umd
            
                
          <form id="form-0" data-twe-active-validation="true">
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isNumber|isLongerThan(2)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput1"
                placeholder="Example label" />
              <label
                for="exampleInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isEmail|contains(test)">
              <input
                type="text"
                name="email"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput2"
                placeholder="Example label" />
              <label
                for="exampleInput2"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <div
              class="relative mb-3"
              data-twe-datepicker-init
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isDate">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Select a date" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Select a date</label
              >
            </div>
            <div
              class="relative mb-3"
              data-twe-timepicker-init
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|is12hFormat">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput3" />
              <label
                for="exampleInput3"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Select a time</label
              >
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
            <button
              class="inline-block rounded px-2 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-danger hover:text-danger-600 focus:text-danger-600 focus:outline-none focus:ring-0 active:text-danger-700"
              id="dispose">
              Dispose validation
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            Datepicker,
            Timepicker,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Input, Datepicker, Timepicker });
    
          const fullValidationDisposeBtn = document.getElementById("dispose");
          const fullValidationForm = document.getElementById("form-0");
        
          const fullValidation = new Validation(fullValidationForm, {
            customErrorMessages: {
              contains: "The field must contain the '{contains}' word",
            },
            customRules: {
              contains: (value, message, string) => {
                return value.includes(string)
                  ? true
                  : message.replace("{contains}", string);
              },
            },
            submitCallback: (e, valid) => {
              console.log("Do something ...", "Validation passed: ", valid);
            },
          });
        
          fullValidationDisposeBtn.addEventListener("click", (e) => {
            e.preventDefault();
            fullValidation.dispose();
          });
        
          fullValidationForm.addEventListener("invalid.twe.validation", (e) => {
            console.log("Something went wrong!");
          });
          fullValidationForm.addEventListener("valid.twe.validation", (e) => {
            console.log("All good!");
          });
          
            
        
            
                
          const fullValidationDisposeBtn = document.getElementById("dispose");
          const fullValidationForm = document.getElementById("form-0");
        
          const fullValidation = new twe.Validation(fullValidationForm, {
            customErrorMessages: {
              contains: "The field must contain the '{contains}' word",
            },
            customRules: {
              contains: (value, message, string) => {
                return value.includes(string)
                  ? true
                  : message.replace("{contains}", string);
              },
            },
            submitCallback: (e, valid) => {
              console.log("Do something ...", "Validation passed: ", valid);
            },
          });
        
          fullValidationDisposeBtn.addEventListener("click", (e) => {
            e.preventDefault();
            fullValidation.dispose();
          });
        
          fullValidationForm.addEventListener("invalid.twe.validation", (e) => {
            console.log("Something went wrong!");
          });
          fullValidationForm.addEventListener("valid.twe.validation", (e) => {
            console.log("All good!");
          });
          
            
        

    Validation with tooltips

    Use emitted events to show tooltips on validation results.

    • HTML
    • javascript
    • umd
            
                
          <form id="tooltips" class="me-10" data-twe-active-validation="true">
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isLongerThan(4)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0 dark:autofill:shadow-autofill"
                name="name" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Full name
              </label>
              <span
                class="absolute -end-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="fullNameInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isEmail">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0 dark:autofill:shadow-autofill"
                name="email" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Email address
              </label>
              <span
                class="absolute -end-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="emailInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <div
              class="relative mb-4 flex items-stretch"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isLongerThan(10)">
              <textarea
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                rows="3"
                name="issue"></textarea>
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Describe your issue</label
              >
              <span
                class="absolute -end-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="issueInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            Tooltip,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Input });
    
          const tooltipsForm = document.getElementById("tooltips");
    
          const tooltipsInfo = [
            {
              element: document.getElementById("fullNameInfo"),
              name: "name",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 4 characters",
              },
            },
            {
              element: document.getElementById("emailInfo"),
              name: "email",
              message: {
                isRequired: "This value is required",
                isEmail: "Must be a valid email address",
              },
            },
            {
              element: document.getElementById("issueInfo"),
              name: "issue",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 10 characters",
              },
            },
          ];
        
          const generateMessage = (result, message) =>
            `<p class="${result ? 'text-success' : 'text-danger'}">${message}</p>`;
        
          tooltipsInfo.forEach((tooltip) => {
            const title = Object.entries(tooltip.message)
              .map(([key, value]) => generateMessage(false, value))
              .join("");
        
            tooltip.instance = new Tooltip(tooltip.element, {
              html: true,
              template: `
                <div>
                  <div class="bg-white text-xs p-4 ms-4 rounded border dark:bg-body-dark dark:border-black/40" data-twe-tooltip-inner-ref></div>
                </div>
              `,
              placement: "right",
              title,
            });
          });
        
          const tooltipsValidation = new Validation(tooltipsForm);
        
          tooltipsForm.addEventListener("valueChanged.twe.validation", (e) => {
            const element = tooltipsInfo.find(
              (tooltip) => tooltip.name === e.value.name
            );
            element.instance.dispose();
        
            const title = Object.entries(element.message)
              .map(([key, value]) => {
                const result = e.value.validation.find(
                  (res) => key === res.name
                ).result;
                return generateMessage(result, value);
              })
              .join("");
        
            const borderColor =
              e.value.result === "valid" ? "border-success" : "border-danger";
        
            element.instance = new Tooltip(element.element, {
              html: true,
              template: `
                <div>
                  <div class="bg-white text-xs p-4 ms-4 rounded border dark:bg-body-dark dark:border-black/40" data-twe-tooltip-inner-ref></div>
                </div>
              `,
              placement: "right",
              title: title,
            });
          });
          
            
        
            
                
          const tooltipsForm = document.getElementById("tooltips");
    
          const tooltipsInfo = [
            {
              element: document.getElementById("fullNameInfo"),
              name: "name",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 4 characters",
              },
            },
            {
              element: document.getElementById("emailInfo"),
              name: "email",
              message: {
                isRequired: "This value is required",
                isEmail: "Must be a valid email address",
              },
            },
            {
              element: document.getElementById("issueInfo"),
              name: "issue",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 10 characters",
              },
            },
          ];
        
          const generateMessage = (result, message) =>
            `<p class="${result ? 'text-success' : 'text-danger'}">${message}</p>`;
        
          tooltipsInfo.forEach((tooltip) => {
            const title = Object.entries(tooltip.message)
              .map(([key, value]) => generateMessage(false, value))
              .join("");
        
            tooltip.instance = new twe.Tooltip(tooltip.element, {
              html: true,
              template: `
                <div>
                  <div class="bg-white text-xs p-4 ms-4 rounded border dark:bg-body-dark dark:border-black/40" data-twe-tooltip-inner-ref></div>
                </div>
              `,
              placement: "right",
              title,
            });
          });
        
          const tooltipsValidation = new twe.Validation(tooltipsForm);
        
          tooltipsForm.addEventListener("valueChanged.twe.validation", (e) => {
            const element = tooltipsInfo.find(
              (tooltip) => tooltip.name === e.value.name
            );
            element.instance.dispose();
        
            const title = Object.entries(element.message)
              .map(([key, value]) => {
                const result = e.value.validation.find(
                  (res) => key === res.name
                ).result;
                return generateMessage(result, value);
              })
              .join("");
        
            const borderColor =
              e.value.result === "valid" ? "border-success" : "border-danger";
        
            element.instance = new twe.Tooltip(element.element, {
              html: true,
              template: `
                <div>
                  <div class="bg-white text-xs p-4 ms-4 rounded border dark:bg-body-dark dark:border-black/40" data-twe-tooltip-inner-ref></div>
                </div>
              `,
              placement: "right",
              title: title,
            });
          });
          
            
        

    Show results with Alert

    Use the data provided by events to show the validation results with an Alert.

    Result
    • HTML
    • javascript
    • umd
            
                
          <form id="form-results" data-twe-active-validation="true">
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isLongerThan(2)">
              <input
                type="text"
                name="name"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleAlertInput1"
                placeholder="Example label" />
              <label
                for="exampleAlertInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Full name
              </label>
            </div>
            <div
              class="relative mb-3"
              data-twe-input-wrapper-init
              data-twe-validate="input"
              data-twe-validation-ruleset="isRequired|isEmail">
              <input
                type="text"
                name="email"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleAlertInput2"
                placeholder="Example label" />
              <label
                for="exampleAlertInput2"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                >Email address
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
              data-twe-submit-btn-ref>
              Validate
            </button>
          </form>
    
          <div
            id="result-container"
            class="fixed right-4 top-4 z-[100] mb-3 hidden w-1/4 items-center rounded-lg bg-primary-100 px-6 py-4 text-base text-primary-800 data-[twe-alert-show]:inline-flex"
            role="alert"
            data-twe-alert-init
            data-twe-autohide="true"
            data-twe-delay="4000">
            Result
          </div>
          
            
        
            
                
          import {
            Validation,
            Input,
            Alert,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Input, Alert });
    
          const resultContainer = document.getElementById("result-container");
          const alertInstance = Alert.getInstance(resultContainer);
        
          const resultsForm = document.getElementById("form-results");
        
          const resultValidation = new Validation(resultsForm);
        
          resultsForm.addEventListener("valid.twe.validation", (e) => {
            const results = [];
            resultsForm.querySelectorAll("input").forEach((input) => {
              results.push({ [input.name]: input.value });
            });
        
            resultContainer.innerHTML = `
          <div>
            <h3 class="mb-3">Validation passed! Here is the result:</h3>
            <div>${JSON.stringify(results, null, 2)}</div>
          </div>
          `; alertInstance.show(); });
          
            
        
            
                
          const resultContainer = document.getElementById("result-container");
          const alertInstance = twe.Alert.getInstance(resultContainer);
        
          const resultsForm = document.getElementById("form-results");
        
          const resultValidation = new twe.Validation(resultsForm);
        
          resultsForm.addEventListener("valid.twe.validation", (e) => {
            const results = [];
            resultsForm.querySelectorAll("input").forEach((input) => {
              results.push({ [input.name]: input.value });
            });
        
            resultContainer.innerHTML = `
          <div>
            <h3 class="mb-3">Validation passed! Here is the result:</h3>
            <div>${JSON.stringify(results, null, 2)}</div>
          </div>
          `; alertInstance.show(); });
          
            
        

    Custom feedback messages

    You can set the feedback messages to have the content you want. Simply add data-twe-invalid-feedback and data-twe-valid-feedback attributes with your custom message.

    Sample image

    Sign in with

    Or

    Forgot password?

    Don't have an account? Register

    • HTML
    • javascript
            
                
          <div>
            <!-- Left column container with background-->
            <div
              class="flex h-full flex-wrap items-center justify-center lg:justify-between">
              <div
                class="shrink-1 mb-12 grow-0 basis-auto md:mb-0 md:w-9/12 md:shrink-0 lg:w-6/12 xl:w-6/12">
                <img
                  src="https://tecdn.b-cdn.net/img/Photos/new-templates/bootstrap-login-form/draw2.webp"
                  class="w-full"
                  alt="Sample image" />
              </div>
    
              <!-- Right column container -->
              <div class="mb-12 md:mb-0 md:w-8/12 lg:w-5/12 xl:w-5/12">
                <form data-twe-validation-init data-twe-active-validation="true">
                  <!--Sign in section-->
                  <div
                    class="flex flex-row items-center justify-center lg:justify-start">
                    <p class="mb-0 me-4 text-lg">Sign in with</p>
    
                    <!-- Facebook -->
                    <button
                      type="button"
                      data-twe-ripple-init
                      data-twe-ripple-color="light"
                      class="mx-1 inline-block h-9 w-9 rounded-full bg-primary fill-white p-2 uppercase leading-normal shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
                      <!-- Facebook -->
                      <span class="[&>svg]:mx-auto [&>svg]:h-3.5 [&>svg]:w-3.5">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          viewBox="0 0 320 512">
                          <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc. -->
                          <path
                            d="M80 299.3V512H196V299.3h86.5l18-97.8H196V166.9c0-51.7 20.3-71.5 72.7-71.5c16.3 0 29.4 .4 37 1.2V7.9C291.4 4 256.4 0 236.2 0C129.3 0 80 50.5 80 159.4v42.1H14v97.8H80z" />
                        </svg>
                      </span>
                    </button>
    
                    <!-- X -->
                    <button
                      type="button"
                      data-twe-ripple-init
                      data-twe-ripple-color="light"
                      class=" mx-1 inline-block h-9 w-9 rounded-full bg-primary fill-white p-2 uppercase leading-normal shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
                      <!-- X -->
                      <span class="[&>svg]:mx-auto [&>svg]:h-3.5 [&>svg]:w-3.5">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          viewBox="0 0 512 512">
                          <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc. -->
                          <path
                            d="M389.2 48h70.6L305.6 224.2 487 464H345L233.7 318.6 106.5 464H35.8L200.7 275.5 26.8 48H172.4L272.9 180.9 389.2 48zM364.4 421.8h39.1L151.1 88h-42L364.4 421.8z" />
                        </svg>
                      </span>
                    </button>
    
                    <!-- Linkedin -->
                    <button
                      type="button"
                      data-twe-ripple-init
                      data-twe-ripple-color="light"
                      class=" mx-1 inline-block h-9 w-9 rounded-full bg-primary fill-white p-2 uppercase leading-normal shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong">
                      <!-- Linkedin -->
                      <span class="[&>svg]:mx-auto [&>svg]:h-3.5 [&>svg]:w-3.5">
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          viewBox="0 0 448 512">
                          <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc. -->
                          <path
                            d="M100.3 448H7.4V148.9h92.9zM53.8 108.1C24.1 108.1 0 83.5 0 53.8a53.8 53.8 0 0 1 107.6 0c0 29.7-24.1 54.3-53.8 54.3zM447.9 448h-92.7V302.4c0-34.7-.7-79.2-48.3-79.2-48.3 0-55.7 37.7-55.7 76.7V448h-92.8V148.9h89.1v40.8h1.3c12.4-23.5 42.7-48.3 87.9-48.3 94 0 111.3 61.9 111.3 142.3V448z" />
                        </svg>
                      </span>
                    </button>
                  </div>
    
                  <!-- Separator between social media sign in and email/password sign in -->
                  <div
                    class="my-4 flex items-center before:mt-0.5 before:flex-1 before:border-t before:border-neutral-300 after:mt-0.5 after:flex-1 after:border-t after:border-neutral-300 dark:before:border-neutral-500 dark:after:border-neutral-500">
                    <p
                      class="mx-4 mb-0 text-center font-semibold dark:text-neutral-200">
                      Or
                    </p>
                  </div>
    
                  <!-- Email input -->
                  <div
                    class="relative mb-6"
                    data-twe-input-wrapper-init
                    data-twe-validate="input"
                    data-twe-validation-ruleset="isRequired|isEmail"
                    data-twe-invalid-feedback="The email address is invalid"
                    data-twe-valid-feedback="The email address is valid">
                    <input
                      type="text"
                      class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                      id="exampleFormControlLogin1"
                      placeholder="Email address" />
                    <label
                      for="exampleFormControlLogin1"
                      class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[1.15rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                      >Email address
                    </label>
                  </div>
    
                  <!-- Password input -->
                  <div
                    class="relative mb-6"
                    data-twe-input-wrapper-init
                    data-twe-validate="input"
                    data-twe-validation-ruleset="isRequired|isLongerThan(6)"
                    data-twe-invalid-feedback="Please provide a password longer than 6 characters"
                    data-twe-valid-feedback="Your password is longer than 6 characters!">
                    <input
                      type="password"
                      class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                      id="exampleFormControlLogin2"
                      placeholder="Password" />
                    <label
                      for="exampleFormControlLogin2"
                      class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[1.15rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                      >Password
                    </label>
                  </div>
    
                  <div class="mb-6 flex items-center justify-between">
                    <!-- Remember me checkbox -->
                    <div
                      class="relative mb-[0.125rem] mt-3 block min-h-[1.5rem] ps-[1.5rem]"
                      data-twe-validate="checkbox"
                      data-twe-validation-ruleset="isChecked">
                      <input
                        class="relative float-left -ms-[1.5rem] me-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-secondary-500 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-checkbox before:shadow-transparent before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ms-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-black/60 focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-black/60 focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-checkbox checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ms-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent rtl:float-right dark:border-neutral-400 dark:checked:border-primary dark:checked:bg-primary"
                        type="checkbox"
                        value=""
                        id="exampleFormControlLogin3" />
                      <label
                        class="inline-block ps-[0.15rem] hover:cursor-pointer"
                        for="exampleFormControlLogin3">
                        Remember me
                      </label>
                    </div>
    
                    <!--Forgot password link-->
                    <a class="mt-3" href="#!">Forgot password?</a>
                  </div>
    
                  <!-- Login button -->
                  <div class="text-center lg:text-left">
                    <button
                      type="button"
                      class="inline-block w-full rounded bg-primary px-7 pb-2 pt-3 text-sm font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-primary-accent-300 hover:shadow-primary-2 focus:bg-primary-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-primary-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
                      data-twe-ripple-init
                      data-twe-ripple-color="light"
                      data-twe-submit-btn-ref>
                      Login
                    </button>
    
                    <!-- Register link -->
                    <p class="mb-0 mt-2 pt-1 text-sm font-semibold">
                      Don't have an account?
                      <a
                        href="#!"
                        class="text-danger transition duration-150 ease-in-out hover:text-danger-600 focus:text-danger-600 active:text-danger-700"
                        >Register</a
                      >
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            Ripple,
            initTWE,
          } from "tw-elements";
          
          initTWE({ Validation, Input, Ripple });
          
            
        

    Related resources

    Tutorials:

    focus active and others dark mode spacing utility first rounded corners cards sizing inputs forms

    Extended Docs:

    datepicker file input form templates input group login form registration form search select textarea timepicker border opacity borders center grid items dark theme display flex icons position spacing

    Generators and builders:

    Form drag & drop Typography SVG icon Instagram Filters button card table flexbox logo grid footer

    Design System (Figma):

    introduction art of prioritization de emphasize with no mercy lowering contrast beyond borders let it breathe user experience do not start with the roof secondary questions project personality design system principles tips and tricks
    • Basic example
    • Advanced Example
    • Existing validation rules
    • Supported components
    • Select
    • Datepicker
    • Timepicker
    • Input Group
    • Textarea
    • Checkbox
    • Switch
    • Radio
    • Active validation
    • Custom validation
    • Validation with tooltips
    • Show results with Alert
    • Custom feedback messages
    • Related resources

    Validation - API


    Import

    Importing components depends on how your application works. If you intend to use the TW elements ES format, you must first import the component and then initialize it with the initTWE method. If you are going to use the UMD format, just import the tw-elements package.

    • javascript
    • umd
            
                
            import { Validation, initTWE } from "tw-elements";
            initTWE({ Validation });
            
            
        
            
                
            import "tw-elements";
            
            
        

    Via data attributes

    Elements with the data-twe-validation-init attribute will be automatically initialized - you can set all available options with data attributes. For ES format, you must first import and call the initTWE method.

    • HTML
            
                
            <form data-twe-validation-init>
              <div
                class="relative mb-3"
                id="input-1"
                data-twe-input-wrapper-init
                data-twe-validate="input">
                <input
                  type="text"
                  class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[twe-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-white dark:placeholder:text-neutral-300 dark:autofill:shadow-autofill dark:peer-focus:text-primary [&:not([data-twe-input-placeholder-active])]:placeholder:opacity-0"
                  id="exampleFormControlInput1"
                  placeholder="Example label" />
                <label
                  for="exampleFormControlInput1"
                  class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[twe-input-state-active]:-translate-y-[0.9rem] peer-data-[twe-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-400 dark:peer-focus:text-primary"
                  >Example label
                </label>
              </div>
            </form>
            
            
        

    Via JavaScript

    You can access an instance from your Javascript code, by using the getInstance static method of the Input class - it allows making use of all the public methods listed in the Methods section.

    • javascript
    • umd
            
                
            const myValidation = new Validation(document.getElementById("myValidation"), options, classes);
            
            
        
            
                
            const myValidation = new twe.Validation(document.getElementById("myValidation"), options, classes);
            
            
        

    Options

    Options can be passed via data attributes or JavaScript. For data attributes, append the option name to data-twe-, as in data-twe-active-validation="true".

    Name Type Default Description
    activeValidation Boolean false Adds listeners for input events. Checks the validation elements with every input update.
    customErrorMessages Object - Changes the default error messages for each validation type and adds new ones.
    customRules Object - Adds new rules to the existing rule set.
    disableFeedback Boolean false Disables the feedback messages for all validation elements.
    invalidFeedback String "Something is wrong!" Changes the default invalid feedback message for all validation elements.
    submitCallback Function Callback function that is called when the form is submitted and all elements were validated. Example: submitCallback: (e, isValid) => { console.log("Do something ...") }
    validFeedback String "Looks good!" Changes the default valid feedback message for all validation elements.

    Classes

    Custom classes can be passed via data attributes or JavaScript. For data attributes, append the class name to data-twe-class, as in data-twe-class-notch-leading-valid="border-[#ff0] dark:border-[#ff0] group-data-[twe-input-focused]:shadow-[-1px_0_0_#ff0,_0_1px_0_0_#ff0,_0_-1px_0_0_#ff0] group-data-[twe-input-focused]:border-[#ff0]"

    Name Default Description
    notchLeadingValid border-success dark:border-success group-data-[twe-input-focused]:shadow-notch-1 group-data-[twe-input-focused]:shadow-success group-data-[twe-input-focused]:border-success Sets border and shadow of the valid leading notch.
    notchMiddleValid border-success dark:border-success group-data-[twe-input-focused]:shadow-notch-2 group-data-[twe-input-focused]:shadow-success group-data-[twe-input-focused]:border-success Sets border and shadow of the valid middle notch.
    notchTrailingValid border-success dark:border-success group-data-[twe-input-focused]:shadow-notch-3 group-data-[twe-input-focused]:shadow-success group-data-[twe-input-focused]:border-success Sets border and shadow of the valid trailing notch.
    notchLeadingInvalid border-danger dark:border-danger group-data-[twe-input-focused]:shadow-notch-1 group-data-[twe-input-focused]:shadow-danger group-data-[twe-input-focused]:border-danger Sets border and shadow of the invalid leading notch.
    notchMiddleInvalid border-danger dark:border-danger group-data-[twe-input-focused]:shadow-notch-2 group-data-[twe-input-focused]:shadow-danger group-data-[twe-input-focused]:border-danger Sets border and shadow of the invalid middle notch.
    notchTrailingInvalid border-danger dark:border-danger group-data-[twe-input-focused]:shadow-notch-3 group-data-[twe-input-focused]:shadow-danger group-data-[twe-input-focused]:border-danger Sets border and shadow of the invalid trailing notch.
    basicInputValid !border-success focus:!border-success focus:!shadow-inset focus:!shadow-success Sets border and shadow of the valid input element.
    basicInputInvalid !border-danger focus:!border-danger focus:!shadow-inset focus:!shadow-danger Sets border and shadow of the invalid input element.
    checkboxValid checked:!border-success checked:!bg-success checked:after:!bg-success Sets border and background of the valid checkbox element and its checkmark.
    checkboxInvalid checked:!border-danger checked:!bg-danger checked:after:!bg-danger Sets border and background of the invalid checkbox element and its checkmark.
    radioValid checked:!border-success checked:after:!bg-success Sets border and background of the valid radio element and its checkmark.
    radioInvalid checked:!border-danger checked:after:!bg-danger Sets border and background of the invalid radio element and its checkmark.
    labelValid !text-success Sets the text color of the valid label element.
    labelInvalid !text-danger Sets the text color of the invalid label element.
    validFeedback absolute top-full left-0 m-1 w-auto text-sm text-success animate-[fade-in_0.3s_both] Sets the position, color and animation of the valid feedback message element.
    invalidFeedback absolute top-full left-0 m-1 w-auto text-sm text-danger animate-[fade-in_0.3s_both] Sets the position, color and animation of the invalid feedback message element.
    elementValidated mb-8 Classes that are added to the validated elements when they are validated and feedback is shown.

    Methods

    Asynchronous methods and transitions:
    All API methods are asynchronous and start a transition. They return to the caller as soon as the transition is started but before it ends. In addition, a method call on a transitioning component will be ignored.

    Method Description Example
    dispose Disposes a Validation instance myValidation.dispose()
    getInstance Static method which allows you to get the Validation instance associated to a DOM element. Validation.getInstance(validationEl)
    getOrCreateInstance Static method which returns the Validation instance associated to a DOM element or create a new one in case it wasn't initialized. Validation.getOrCreateInstance(validationEl)
    • javascript
    • umd
            
                
            const validationEl = document.getElementById('myValidation');
            const validation = new Validation(validationEl);
            validation.dispose();
            
            
        
            
                
            const validationEl = document.getElementById('myValidation');
            const validation = new twe.Validation(validationEl);
            validation.dispose();
            
            
        

    Events

    Event type Description
    validated.twe.validation This event is fired when a validation is performed.
    valid.twe.validation This event is fired when a validation is performed and the element is valid.
    invalid.twe.validation This event is fired when a validation is performed and the element is invalid.
    valueChanged.twe.validation This event is fired when the value of the input element changes.
    • JavaScript
            
                
                const validation = document.getElementById("myValidation");
                validation.addEventListener("valueChanged.twe.validation", (event) => {
                  console.log("Do something ...");
                });
              
            
        
    • Import
    • Usage
    • Options
    • Classes
    • Methods
    • Events
    Get useful tips & free resources directly to your inbox along with exclusive subscriber-only content.
    Join our mailing list now
    © 2024 Copyright: MDBootstrap.com

    Access restricted

    To view this section you must have an active PRO account

    Log in to your account or purchase an TWE subscription if you don't have one.

    Buy TWE PRO