使用 simple_form 个条目输入空数组值

Empty array value being input with simple_form entries

我对 rails 和 simple_form 还是个新手,一直在尝试实现多个 select 选项来为用户提供多个角色。

当前输入如下所示

<%= f.input :secondary_role, :collection => UseridRole::VALUES, :include_blank => false,:label => "Secondary Role(s):", :input_html => {  :class => " simple_form_bgcolour simple_form_position overide_selection_field_width", :size => 4, multiple: true } %>

所以,这确实有效,但在我的数组开头包含一个空值:

"secondary_role" : [
        "",
        "admin"
    ]

我有上面相同的代码,它适用于我的 primary_role 值,它是一个字符串,但是我的 secondary_role 可以有多个值,所以存储为一个数组。

我应该在哪里寻找解决这个问题的方法?

似乎 Rails 正在向集合中添加一个隐藏字段。尝试将 include_hidden: false 添加到您的表单输入中。

有几种方法可以避免 multi-selects 的空值。

与网络开发中的大多数事情一样,有一百万种方法可以给这只猫蒙皮。

选项 1:JS 捕获并删除

如果你选择,你可以在 JS 中捕获表单,删除空字符串然后调用 form.submit -- 在这种情况下,对你来说,与其他选项相比没有真正的好处

选项 2:强参数控制器捕获

您可以在参数方法中使用拒绝空值

def object_params
  obj_p = params.require(:user).permit(:primary_role, secondary_role: [] )
  obj_p[:secondary_role].reject! { |role| role if role == ""}
  up
end

选项 3:拒绝模型中的空白

#app/models/object_model.rb
before_save :remove_blanks

private 
def remove_blanks
  self.secondary_role.reject!(&:blank?).to_s
end

如果选项可能会在您的控制器之外更新,那么 DRYer 方式就在模型中。


编辑

如果您试图捕获已删除的数组元素,则无法删除所有空白,如果数组中仍有一个项目(至少有一个),它会起作用,但如果您删除所有元素,它根本不会将表单元素传递给控制器​​。

改为使用表单指示用户设置为 nil 并使用上面的模型方法:

<%= f.input :secondary_role, :collection => UseridRole::VALUES, :include_blank => "Remove All Secondary Role(s)", :label => "Secondary Role(s):", :input_html => {  :class => " simple_form_bgcolour simple_form_position overide_selection_field_width", :size => 4, multiple: true } %>

此外,如果选择该选项,我可能会使用 javascript 取消选择其他所有内容,这样用户就可以清楚地知道将要发生什么。

像这样的 js 片段

var el = document.querySelector("#user_secondary_role")
el.addEventListener('change', function() {
  if (el.value == "") {
    roles = el.querySelectorAll("option")
    for (var value of roles) {
      (value.value == "") ? value.selected = true : value.selected = false
    }
  }
});

然后在您的模型中,对选项 3 中最后列出的 before_save 调用使用 remove_blanks 方法。

故障。这是正在发生的事情。

  1. 在您的表单元素中,继续 include_blank - 如果元素为空,这将确保传递“”。接下来,确保 include_blank 有一个标题,其值始终为“”,但您需要为用户提供有意义的点击内容。
  2. 添加一些 javascript 这样当用户确实单击 "Remove All Secondary Roles" 时 - 他们前面的表单会更改并取消选择其他选项。
  3. 模型方法将删除空白,简单明了,但这将不起作用,除非您允许传入空白,否则您的元素将为空并且永远不会到达您的 controller/model .您可以通过查看 development.log 并检查 POST.
  4. 中传递的参数来验证这一点