【问题标题】:Empty array value being input with simple_form entries使用 simple_form 条目输入空数组值
【发布时间】:2018-07-14 17:44:34
【问题描述】:

我对 rails 和 simple_form 还很陌生,并且一直在尝试实现一个多选选项来为用户提供多个角色。

当前输入如下所示

<%= 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 可以有多个值,因此存储为一个数组。

我应该去哪里解决这个问题?

【问题讨论】:

    标签: ruby-on-rails simple-form simple-form-for


    【解决方案1】:

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

    【讨论】:

    • 是的,这是一个 Rails 问题,谢谢。还在这里找到了解决方案 - github.com/rails/rails/issues/5402
    • 有趣的是我从来没有这样做过——而且它看起来自 2012 年以来就得到了支持。回到我一直在编码的岩石上,我猜。 :)
    【解决方案2】:

    有几个选项可以摆脱多选的空值。

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

    选项 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 sn-p

    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,以便当用户单击“删除所有次要角色”时 - 他们前面的表单会更改并取消选择其他选项。
    3. 模型方法将删除空白,简单明了,但除非您允许传入空白,否则这将不起作用,否则您的元素将是空的并且永远不会到达您的控制器/模型。您可以通过查看您的 development.log 并检查 POST 中传递的参数来验证这一点。

    【讨论】:

    • 太棒了!我确实找到了上面的解决方案,但这更有帮助,谢谢!
    • 既然你在这里,我可以为相关问题挑选你的大脑吗?我还希望检查用户是否取消选择选择选项。目前,如果已经为辅助角色存储了现有值,并且用户取消选择该选项并按保存,则表单似乎不会覆盖以前的值以将其设置为空白,这就是我想要的。解决这个问题的最好方法是在我的模型中检查 params[:secondary_role],如果为零,设置 @user.secondary_role = [ ] ?
    猜你喜欢
    • 2015-05-21
    • 1970-01-01
    • 2021-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-14
    相关资源
    最近更新 更多