Emphatic Invalids
Lightweight gem that utilizes Rails server-side model validations to display client-side error messages for Ajax form submissions.
screenshot of invalid form submission
To see it in action: cd test/dummy
and start the server rails s
. Then just navigate to http://localhost:3000/registrations/new
and submit the empty form as is.
Features
- After an invalid Ajax form submission any fields that failed Rails model validation will be highlighted.
- Rails validation error message are displayed as a jQuery UI tooltip whenever an invalid field has focus or is hovered over. This way when there are several invalid fields the messages aren't all displayed at once.
- Adjusts the form fields' tab index* so the user can easily tab from one invalid field to the next and finally to a submit button.
- Once an invalid field's value has been changed the highlight is removed from it.
- Also works with deeply nested attributes
* For the best field navigation experience the model validations should be declared in the same order that the fields appear in the form. This includes nested attributes so that their associations and validations are declared in the same order of the form also. Compare views/registrations/_form.html.haml with the models in the test/dummy application for an example
Installation
Add this line to your application's Gemfile:
gem 'emphatic_invalids'
And then execute:
$ bundle
In one of your javascript files require emphatic_invalids/script.coffee
In one of your stylesheet files require emphatic_invalids/style.css
Usage
Javascript
Register your forms by adding the following to one of your project's javascript/coffeescript files:
document.addEventListener("DOMContentLoaded", ->
window.EmphaticInvalids.registerForms()
)
# or if using plain js
# document.addEventListener("DOMContentLoaded", function() {
# window.EmphaticInvalids.registerForms()
# )};
The registerForms()
method takes an optional parameter allowing you to select which <form>
elements in your application should utilize the gem (the default value is "form[data-remote=true]"
)
Example:
If you don't want to register all remote forms you can always add you own attribute to the desired forms:
<form data-remote="true" data-highlight-errors="true">
<!-- ... -->
</form>
and just specify that selector in the register call:
$(document).ready( ->
window.EmphaticInvalids.registerForms("form[data-highlight-errors=true"])
)
Controllers
Inside each appropriate controller action, which is usually just update and create you will need to call the emphasize_invalids
method like this:
# posts_controllers.rb
def update
@post = Post.find(params[:id])
# ...
respond_to do |format|
if @post.save
# ...
format.js { render :success } #successfully saved...do whatever's appropriate here
else
emphasize_invalids(@post, format)
end
end
end
Optional
Note: All the following options are used in the test/dummy application. See the views/registrations/_form.html.haml partial
By default the input element (view the particulars) itself will be highlighted, but that can be overwritten at the form or field level with data attribute data-ei-highlight-element **
<input type="text" name="author" data-ei-highlight-element=".field" />
By default the tooltip will be applied to the matching input element itself, but that can be overwritten at the form or field level with a data attribute data-ei-tooltip-element **
<input type="radio" name="choice1" data-ei-tooltip-element="fieldset.rb-group" />
** The value of these attributes should be a selector that will be evaluated in the context of the invalid input's closest matching ancestor
By default the tooltip's position will be centered vertically and 15 pixels to the right of it's target element. The position can be overridden at the form or element level by setting a data attribute data-ei-tooltip-position on the target element. Make sure if you have overridden the target element that the attribute is placed on that specific element. The value needs to be a valid JSON string in the format of the options
argument expected by the jQuery position method.
<form data-remote="true" data-ei-tooltip-position='{"my": "left+2 center", "at": "right center"}'>
<!-- ... -->
</form>
Styling
The styling of the highlighted fields and the tooltips can be adjusted by defining the CSS class .highlight-error
and/or .error-tooltips
anywhere after require emphatic_invalids/style.css
Particulars
Based on each validation error's key the messages are mapped to their corresponding form input elements when an element's:
- name attribute equals the key exactly
- id attribute equals the key exactly
- name attribute ends in "[key]" or "[key][]"
- data-ei-field-alias attribute equals the key
When the actual form element (something like a Rails date_select) doesn't match the validation field's identifier, an element can be specified using the data attribute data-ei-field-alias, which should be set to the validation error key.
%div.field{"data-ei-field-alias" => "date_of_birth"}
= form.date_select :date_of_birth, id: :registration_date_of_birth
If you aren't getting the results you expect it may be helpful to view the actual validation error data being sent by the gem. Add a hidden input element to your form with id="log-invalids"
and the data will be logged to your browser's javascript console.
Contributing
Feel free.
TODO:
- Add specs once rspec and rails 5.1 play nice together
- Decide if there should be an option for flash[:error] to be set in EmphaticInvalids::Renderer
- Add the ability to display errors for local (HTML) form submissions as well
License
The gem is available as open source under the terms of the MIT License.