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.
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.