Stimulus Inline Input Validations

A Stimulus controller for validating html form inputs and rendering their errors in a custom error element.

status badge for download count of package status badge for version of package status badge for status of CI tests for package badge for licnese of package

1. Install the package

              
yarn add stimulus-inline-input-validations
            
            

2. Import and register the controller

              
import { InputValidator } from "stimulus-inline-input-validations"
application.register("input-validator", InputValidator)
              
            

Validations as HTML attributes

Length

data-validates-length= "5,10"

Validates min,max length of a string

Presence

data-validates-presence

Validates that a field is not blank

Numericality

data-validates-numericality

Validates if a field is a number

Email

data-validates-email

Validates email format

Strong password

data-validates-strong-password

Validates strong password

Multiple Validations

Multiple HTML attributes

data-validates-*

Length, Presence, Email

JSON

data-validations= '[{"presence": true}, {"length": {"min":6, "max":128}}, {"strong_password":true}]'

Bulk validations via a json-friendly string

Custom Error Styles

CSS

data-errors-styles-css= "font-size: 14px; color: blue"

font-size: 14px; color: blue

Classes

data-errors-styles-class= "font-bold text-purple-600"

font-bold text-purple-600 (Tailwind)

How to use

1. Add `data-controller="input-validator"` to your form or any parent element of `<input>` elements you want to validate.

            
<form data-controller="input-validator">
...
</form>
            
          

2. Add `data-input-validator-target` and `data-field` attributes to an input element.

            
<input type="text" data-input-validator-target="field" data-field="userName">
            
          

3. Add an errors element with matching `data-field` attribute

            
<div data-input-validator-target="errors" data-field="userName"></div>
            
          

4. Add, mix, and match validations

            
<input ... data-validates-length="5,10" data-validates-numericality data-validates-email>
            
          

Validations run on input/blur events, and will render any errors inside the errors element

            
<div data-input-validator-target="errors" data-field="userName">
  <div error="length-min">Too short. Minimum 5 characters</div>
  <div error="numericality">Must be a number</div>
  <div error="email">Invalid email format</div>
</div>
            
          

Usage in Rails:

Leveraging existing model validations in Rails form helpers

1. Add a `json_validations_for` method to `application_helper.rb`

            
module ApplicationHelper
  def json_validations_for(model, field)
    validations_hash = {}

    validators = model.class.validators_on(field)
    validators.each do |validator|
      validator_name = validator.class.name.demodulize.underscore.to_sym

      if validator_name == :length_validator
        options = validator.options.dup
        validations_hash[:length] = { min: options[:minimum].present? ? options[:minimum] : 1,
        max: options[:maximum].present? ? options[:maximum] : 1000 }
      end

      validations_hash[:presence] = true if validator_name == :presence_validator
      validations_hash[:numericality] = true if validator_name == :numericality_validator
    end

    validations_hash[:strong_password] = true if field == :password
    validations_hash[:email] = true if field == :email

    validations = validations_hash.map do |key, value|
      { key.to_s => value }
    end

    validations.to_json.html_safe
  end
end
            
          

2. Use the `json_validations_for` helper method in your Rails form helpers

            
<%= f.text_field :email, 
                 data: { 
                  input_validator_target:"field",
                  field: :email,
                  validations: json_validations_for(@user, :email) 
                 }%>
<div data-input-validator-target="errors" data-field="email"></div>
            
          

Made with in Akron, OH by Mike Ray Arriaga