Skip to content
jmarceli edited this page Mar 31, 2015 · 12 revisions

Select2 validation on submit

To enable the validation of select2 inputs on form Submission add the following to your javascript after requiring rails.validations

ClientSideValidations.selectors.validate_inputs += ', .select2-container:visible + :enabled[data-validate]';
ClientSideValidations.selectors.inputs += ', .select2-container:visible + :enabled[data-validate]';

It is just validation after form submission. Simple but not "live".

Possible complete Select2 integration

Full live (client side) validation, "developed" to use with simple_form and foundation markup (should work in other cases too).

Create separate .coffee file e.g. client_side_select2.js.coffee with following code:

# Add select2 support
ClientSideValidations.selectors.validate_inputs += ', select[data-select2-validate]'
ClientSideValidations.selectors.inputs += ', .select2-container'

getSelect2 = (element) ->
  $(element).parent().find('select')

$.fn.base = window.ClientSideValidations.enablers.input

window.ClientSideValidations.enablers.input = (element) ->
  extend = ->
    unless $(element).hasClass 'select2-container'
      $.fn.base(element)
    else
      $placeholder = $(element)
      $select = $placeholder.parent().find('select')
      form   = $select[0].form
      $form  = $(form)

      if $select.attr('data-select2-validate')
        # only focus event should be handled by placeholder
        $placeholder.on(event, binding) for event, binding of {
          'focusout.ClientSideValidations': ->
            getSelect2(@).isValid(form.ClientSideValidations.settings.validators)
        }
        $select.on(event, binding) for event, binding of {
          'change.ClientSideValidations':   -> getSelect2(@).data('changed', true)
          # Callbacks
          'element:validate:after.ClientSideValidations':  (eventData) -> ClientSideValidations.callbacks.element.after(getSelect2(@),  eventData)
          'element:validate:before.ClientSideValidations': (eventData) -> ClientSideValidations.callbacks.element.before(getSelect2(@), eventData)
          'element:validate:fail.ClientSideValidations':   (eventData, message) ->
            element = $(@)
            ClientSideValidations.callbacks.element.fail(element, message, ->
              form.ClientSideValidations.addError(element, message)
            , eventData)
          'element:validate:pass.ClientSideValidations':   (eventData) ->
            element = $(@)
            ClientSideValidations.callbacks.element.pass(element, ->
              form.ClientSideValidations.removeError(element)
            , eventData)
        }
  extend()

Require this file after rails.validations in your appplication.js.coffee e.g.:

#= require rails.validations
#= require client_side_select2

Now add data-select2-validate="true" attribute to your select2 select element to get the following markup:

<select data-select2-select="true" data-select2-validate="true" style="display: none;">
  <option value="">Default option</option>
  <option value="1">Option 1</option>
  ... other options ...
</select>

<span class="select2 select2-container select2-container--default" dir="ltr" style="width: 291px;">
  ... rest of the select2 markup ...
</span>

Now everything should work.

Good luck.

I suppose that support for select2 without validation might be an issue with the code above, but I'm not sure.

It could cause issues when used with Turbolinks.

Ajax support

For AJAX support (including turbolinks) you should execute following code to reinitialize validations.

# initialize select2
$select2 = $wrapper.find('[data-select2-select]').select2()
# initialize client_side_validations
$select2.parent().find('.select2-container').enableClientSideValidations()

Of course this should be executed on Ajax success response, only for new elements.