DavyJonesLocker / client_side_validations

Client Side Validations made easy for Ruby on Rails
MIT License
2.69k stars 403 forks source link

Validations not working #739

Closed prodigerati closed 6 years ago

prodigerati commented 6 years ago

Steps to reproduce*

When tabbing out of required field in a simple_form it throws the error below:

Expected behavior*

I would expect html error that field is required.

Actual behavior*

Development Console Error below, nothing happens on the page:
Uncaught TypeError: Cannot read property 'replace' of null
    at Object.add (rails.validations.simple_form.self-7e3c933e617847dc5112ea483c587ef787d395eac1e4dfb64e4a02b624e010ef.js?body=1:25)
    at Object.add (rails.validations.simple_form.self-7e3c933e617847dc5112ea483c587ef787d395eac1e4dfb64e4a02b624e010ef.js?body=1:12)
    at Object.addError (rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:169)
    at rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:230
    at Object.fail (rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:149)
    at HTMLInputElement.element:validate:fail.ClientSideValidations (rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:229)
    at HTMLInputElement.dispatch (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5227)
    at HTMLInputElement.elemData.handle (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:4879)
    at Object.trigger (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5131)
    at HTMLInputElement.<anonymous> (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5861)
add @ rails.validations.simple_form.self-7e3c933e617847dc5112ea483c587ef787d395eac1e4dfb64e4a02b624e010ef.js?body=1:25
add @ rails.validations.simple_form.self-7e3c933e617847dc5112ea483c587ef787d395eac1e4dfb64e4a02b624e010ef.js?body=1:12
addError @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:169
(anonymous) @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:230
fail @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:149
element:validate:fail.ClientSideValidations @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:229
dispatch @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5227
elemData.handle @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:4879
trigger @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5131
(anonymous) @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5861
each @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:371
each @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:138
trigger @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5860
failElement @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:97
executeValidators @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:113
validateElement @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:137
$.fn.isValid @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:50
focusout.ClientSideValidations @ rails.validations.self-4eae4a5924ea8a50f053c1060bee692980f04b1ab77bcab8d76fc8394e6cd042.js?body=1:215
dispatch @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5227
elemData.handle @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:4879
trigger @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5131
simulate @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5485
handler @ jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5786

System configuration*

Rails version: Rails Version 5.2 Ruby version: Ruby Version 4.2.1

Client Side Validations version: client_side_validations 11.1.2 client_side_validations-simple_form 6.6.0 simple_form 4.0.0

Code snippet from your model of the validations*

application.js

//= require jquery
//= require rails-ujs
//= require rails.validations
//= require rails.validations.simple_form

The whole form code from your template*

Form Code:

<div class="card-body">
          <div class="px-3">
              <div class="form-body">
                <h4 class="form-section">
                  <i class="ft-user"></i> Personal Info</h4>
                <%= simple_form_for @user, validate: true do |f| %>
                <%= f.error_notification %>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :first_name, class: 'form-control' %>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :last_name %>
                    </div>
                  </div>
                </div>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :username %>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :email %>
                    </div>
                  </div>
                </div>

                <h4 class="form-section">
                  <i class="ft-file-text"></i> Credentials</h4>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :password %>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.input :password_confirmation %>
                    </div>
                  </div>
                </div>

                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <%= f.association :roles,
                         label_method: :name,
                         value_method: :id,
                         label: 'Assign Roles'
                      %>
                      </select>
                    </div>
                  </div>
                </div>

                <div class="form-group">
                  <%= f.input :active %>
                </div>
              </div>

              <div class="form-actions">
                <%= button_tag "Cancel", class: "btn btn-raised btn-raised btn-warning mr-1" %>
                <%= f.button :submit, class: "btn btn-raised btn-raised btn-primary" %>
              </div>
            <% end %>
          </div>
        </div>

The resulting HTML*

tagliala commented 6 years ago

Hi @prodigerati could you please post, as required

  1. Validation snippet from your model
  2. The resulting HTML

They are important

prodigerati commented 6 years ago

Sorry, here is the model snippet:

EMAIL_REGEX = /[A-Z0-9._%+-]+@test.com/i

validates_presence_of :username, :email, :first_name, :last_name, :role_ids

validates :password,
            :password_confirmation,
            confirmation: true,
            length: { in: 6..25 },
            on: :create

  validates_presence_of :password, :password_confirmation, on: :create

  validates :password,
            :password_confirmation,
            confirmation: true,
            length: { in: 6..25 },
            on: :update,
            allow_blank: true

  validates_uniqueness_of :email, :username
  validates :email, format: EMAIL_REGEX

Below is the resulting HTML:

<form class="simple_form new_user" id="new_user" novalidate="novalidate" data-client-side-validations="{&quot;html_settings&quot;:{&quot;type&quot;:&quot;SimpleForm::FormBuilder&quot;,&quot;error_class&quot;:null,&quot;error_tag&quot;:&quot;div&quot;,&quot;wrapper_error_class&quot;:&quot;form-group-invalid&quot;,&quot;wrapper_tag&quot;:&quot;div&quot;,&quot;wrapper_class&quot;:&quot;form-group&quot;,&quot;wrapper&quot;:&quot;vertical_form&quot;},&quot;number_format&quot;:{&quot;separator&quot;:&quot;.&quot;,&quot;delimiter&quot;:&quot;,&quot;},&quot;validators&quot;:{&quot;user[first_name]&quot;:{&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}]},&quot;user[last_name]&quot;:{&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}]},&quot;user[username]&quot;:{&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}],&quot;uniqueness&quot;:[{&quot;message&quot;:&quot;has already been taken&quot;,&quot;case_sensitive&quot;:true}]},&quot;user[email]&quot;:{&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}],&quot;uniqueness&quot;:[{&quot;message&quot;:&quot;has already been taken&quot;,&quot;case_sensitive&quot;:true}],&quot;format&quot;:[{&quot;message&quot;:&quot;is invalid&quot;,&quot;with&quot;:{&quot;source&quot;:&quot;[A-Z0-9._%+-]+@test.com&quot;,&quot;options&quot;:&quot;gi&quot;}}]},&quot;user[password]&quot;:{&quot;length&quot;:[{&quot;messages&quot;:{&quot;maximum&quot;:&quot;is too long (maximum is 72 characters)&quot;},&quot;maximum&quot;:72},{&quot;messages&quot;:{&quot;minimum&quot;:&quot;is too short (minimum is 6 characters)&quot;,&quot;maximum&quot;:&quot;is too long (maximum is 25 characters)&quot;},&quot;minimum&quot;:6,&quot;maximum&quot;:25}],&quot;confirmation&quot;:[{&quot;message&quot;:&quot;doesn't match Password&quot;,&quot;case_sensitive&quot;:true,&quot;allow_blank&quot;:true},{&quot;message&quot;:&quot;doesn't match Password&quot;,&quot;case_sensitive&quot;:true}],&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}]},&quot;user[password_confirmation]&quot;:{&quot;confirmation&quot;:[{&quot;message&quot;:&quot;doesn't match Password confirmation&quot;,&quot;case_sensitive&quot;:true}],&quot;length&quot;:[{&quot;messages&quot;:{&quot;minimum&quot;:&quot;is too short (minimum is 6 characters)&quot;,&quot;maximum&quot;:&quot;is too long (maximum is 25 characters)&quot;},&quot;minimum&quot;:6,&quot;maximum&quot;:25}],&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}]},&quot;user[role_ids][]&quot;:{&quot;presence&quot;:[{&quot;message&quot;:&quot;can't be blank&quot;}]}}}" action="/users" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓"><input type="hidden" name="authenticity_token" value="4ZCg9MsmDympeiZjf006aip99H0ksLsTfadMlurwABxIQWW/+x6qvL1Obcc+7emCUjTZLIqHngkYeEp3zsEyIg==">                
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group string required user_first_name"><label class="form-control-label string required" for="user_first_name">First name <abbr title="required">*</abbr></label><input class="form-control string required" type="text" name="user[first_name]" id="user_first_name" data-validate="true"></div>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group string required user_last_name"><label class="form-control-label string required" for="user_last_name">Last name <abbr title="required">*</abbr></label><input class="form-control string required" type="text" name="user[last_name]" id="user_last_name" data-validate="true"></div>
                    </div>
                  </div>
                </div>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group string required user_username"><label class="form-control-label string required" for="user_username">Username <abbr title="required">*</abbr></label><input class="form-control string required" type="text" name="user[username]" id="user_username" data-validate="true"></div>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group email required user_email"><label class="form-control-label email required" for="user_email">Email <abbr title="required">*</abbr></label><input class="form-control string email required" type="email" name="user[email]" id="user_email" data-validate="true"></div>
                    </div>
                  </div>
                </div>

                <h4 class="form-section">
                  <i class="ft-file-text"></i> Credentials</h4>
                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group password required user_password"><label class="form-control-label password required" for="user_password">Password <abbr title="required">*</abbr></label><input class="form-control password required" type="password" name="user[password]" id="user_password" data-validate="true"></div>
                    </div>
                  </div>
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group password required user_password_confirmation"><label class="form-control-label password required" for="user_password_confirmation">Password confirmation <abbr title="required">*</abbr></label><input class="form-control password required" type="password" name="user[password_confirmation]" id="user_password_confirmation"></div>
                    </div>
                  </div>
                </div>

                <div class="row">
                  <div class="col-md-6">
                    <div class="form-group">
                      <div class="form-group select required user_roles"><label class="form-control-label select required" for="user_role_ids">Assign Roles <abbr title="required">*</abbr></label><input name="user[role_ids][]" type="hidden" value=""><select class="form-control select required" multiple="multiple" name="user[role_ids][]" id="user_role_ids" data-validate="true"><option value="1">admin</option><option value="2">general</option></select></div>

                    </div>
                  </div>
                </div>

                <div class="form-group">
                  <fieldset class="form-group boolean optional user_active"><div class="form-check"><input name="user[active]" type="hidden" value="0"><input class="form-check-input boolean optional" type="checkbox" value="1" name="user[active]" id="user_active" data-validate="true"><label class="form-check-label boolean optional" for="user_active">Active</label></div></fieldset>
                </div>
              </form>

Thank you for taking time to review!

tagliala commented 6 years ago

Thanks, now I should be able to check this... as soon as I get back my development machine from Apple.

PS: if the above regexp is not a mock or an example for this bug report, please avoid /[A-Z0-9._%+-]+@test.com/i: this will allow new lines, tabulations, spaces and other stuff you don't want in an email address.

Devise regexp for testing email: https://github.com/plataformatec/devise/blob/f220b992c338122226f6fd396056d5a1adf28df8/lib/generators/templates/devise.rb#L171

prodigerati commented 6 years ago

@tagliala any luck figuring this out? Thank you.

tagliala commented 6 years ago

@prodigerati sorry, this will take a while on my side

tagliala commented 6 years ago

Sorry for the late reply, I gave up with my machine and I will let my MBP drain battery instead of sleeping 🤷‍♂️

I'm able to replicate the issue with your form but I've noticed that you have some wrong settings:

image

I would rather expect something like this:

image

Please make sure that error class is not null

Also, your template is creating nested form-group tags (do not wrap f.input :active inside a form group, it will create a form-group wrapper on its own) .

Are you using Bootstrap 4? CSV Simple Form is not ready for TWBS4. Please take a look at: https://github.com/DavyJonesLocker/client_side_validations-simple_form/issues/65

Take a look at your form with the error_class set to something different than null:

image

Anyway, this is not an issue with CSV so I'm closing here but feel free to comment