有没有人使用带有Chosen.js下拉列表的client_side_validations gem?

时间:2012-06-08 16:06:06

标签: ruby-on-rails client-side-validation jquery-chosen

我使用的是selected.js(http://harvesthq.github.com/chosen/)。我想知道是否有人能够一起使用所选择的选择框和client_side_validations。

问题在于,当我们使用selected时,它会隐藏原始的select元素并改为呈现自己的下拉列表,当我们关注时,不会调用验证,并且当显示验证消息时,它会显示原始的select元素因此错误的定位也是正确的。

处理这个问题的好方法是什么,我可以更改ActionView::Base.field_error_proc内部的一些代码,这些代码目前看起来像

 ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
   unless html_tag =~ /^<label/
     %{<div class="field_with_errors">#{html_tag}<label for="#{instance.send(:tag_id)}" class="message">#{instance.error_message.first}</label></div>}.html_safe
   else
     %{<div class="field_with_errors">#{html_tag}</div>}.html_safe
   end
 end

有什么想法吗?

编辑1:

我现在有以下解决方案。

  • 将一个类“chzn-dropdown”应用于我选择的
  • 显示的所有选择
  • 使用client_side_validations Gem
  • 提供的以下回调
clientSideValidations.callbacks.element.fail = function(element, message, callback) {

  if (element.data('valid') !== false) {

    if(element.hasClass('dropdown')){

      chzn_element = $('#'+element.attr('id')+'_chzn');

      console.log(chzn_element);

      chzn_element.append("<label class='message-chzn'>"+message+"</label>");
  }
  else{
    callback();
  }
  }
}

3 个答案:

答案 0 :(得分:1)

关于在所选选项更改时验证未运行的问题,您可以尝试:

selectbox.change(function() { setTimeout(function() { selectbox.focusout() }) });

我仍然在寻找有关验证消息定位的解决方案,因为我真的很想避免篡改客户端验证javascript。

修改

毕竟,这似乎是一个很好的解决方案,为了更接近客户端验证api,我想出了以下内容(可能涉及的人):

var settings = {
    type: 'ActionView::Helpers::FormBuilder',
    input_tag: '<div class="field_with_errors"><span id="input_tag" /><label class="message validationError" /></div>'
};

clientSideValidations.callbacks.element.fail = function (element, message, addError) {
    if ($(element).data('chosen') != null) {
        var chosen = $('#' + element.attr('id') + '_chzn');

        clientSideValidations.formBuilders[settings.type].add(chosen, settings, message);

        // Point the label back to the select box
        $('label[for="' + chosen.attr('id') + '"]').attr('for', element.attr('id'));

        // Mark it as invalid
        chosen.data('valid', false);
    } else {
        addError(element, message);
    }
};

clientSideValidations.callbacks.element.pass = function (element, removeError) {
    if (element.data('chosen') != null) {
        var chosen = $('#' + element.attr('id') + '_chzn');

        clientSideValidations.formBuilders[settings.type].remove(chosen, settings);

        // Un-mark it from invalid
        chosen.data('valid', null);
    } else {
        removeError(element);
    }
};

请注意,我使用数据属性(data-chosen)来初始化所选的选择框。另外,对于标签点击打开选择工作,我明确打开标签上的列表框点击:

// element is the select box

// Delegate click event from related labels to element (this is already done on "good" browsers)
$('label[for="' + element.attr('id') + '"]').click(function() { element.click() });

// Delegate click event on original element and any related labels to open the list
$(element).click(function() { setTimeout(function() { element.trigger('liszt:open'); }, 0); });

答案 1 :(得分:0)

  clientSideValidations.callbacks.element.fail = function(element, message, callback){
    if(element.data("valid") !== false) {
      callback();
      if(element.is("select") && $("#" + element.attr("id") + "_chzn").length > 0){
        element.parent().prepend($("#" + element.attr("id") + "_chzn"));
      }
    }
  }

答案 2 :(得分:0)

试试这个:

告诉gem您要验证选择标记:

ClientSideValidations.selectors.inputs += ', select';

当Chosen的保管箱更改时强制验证:

$('#form_field').chosen().change(function(e) {
  var settings = window.ClientSideValidations.forms[this.form.id];
  $(this).isValid(settings.validators);
});

由于Chosen隐藏了该字段,您需要在视图中明确启用该字段的验证:

<%= form_for ..., :validate => true do |f| %>
...
  <%= f.validate :form_field %>
...
<% end %>