Rails中Simple Form无法向控制器传递motivo参数问题
问题原因
你遇到的核心问题是两个同名的motivo输入框冲突:不管是否隐藏,表单提交时浏览器会将所有带有name="vacacion[motivo]"的字段都发送给控制器,最后一个空的输入框值会覆盖之前填写的内容,导致控制器拿到的motivo始终为空。另外注意你JS里的div选择器和视图里的div id不匹配(视图是id1/id2,JS里写的是#campos_vacaciones_abonadas),这也会导致显示隐藏逻辑失效,需要先修正。
解决办法
方案1:禁用隐藏区域的输入框(最简单)
在切换显示/隐藏div时,给隐藏区域内的motivo输入框添加disabled属性(禁用的字段不会被表单提交),给显示区域的输入框移除禁用属性:
$(document).ready(function(){ $("#vacacion_tipo").change(function(){ const tomadasDiv = $("#id1"); const abonadasDiv = $("#id2"); const tomadasMotivo = tomadasDiv.find("input[name='vacacion[motivo]']"); const abonadasMotivo = abonadasDiv.find("input[name='vacacion[motivo]']"); if(this.value == "tomadas"){ abonadasDiv.hide("slow"); abonadasMotivo.prop("disabled", true); tomadasDiv.show("slow"); tomadasMotivo.prop("disabled", false); } if(this.value == "abonadas"){ tomadasDiv.hide("slow"); tomadasMotivo.prop("disabled", true); abonadasDiv.show("slow"); abonadasMotivo.prop("disabled", false); } }); });
方案2:使用不同的字段名,在控制器统一处理
给两个motivo设置不同的name属性,然后在控制器根据tipo字段的值,将对应的值赋值给模型的motivo:
视图修改:
<div id="id1" style="display:none"> <!-- 其他字段保持不变 --> <%= f.input :motivo_tomadas, input_html: { id: 'motivo_tomadas'},label: 'Motivo de los días tomados' %> </div> <div id="id2" style="display:none"> <!-- 其他字段保持不变 --> <%= f.input :motivo_abonadas, input_html: { id: 'motivo_abonadas'},label: 'Motivo de los días abonados' %> </div>
控制器修改:
def vacacion_params params.require(:vacacion).permit(:tipo, :desde, :hasta, :dias_tomados, :dias_abonados, :motivo_tomadas, :motivo_abonadas).tap do |permitted| permitted[:motivo] = permitted.delete(permitted[:tipo] == 'tomadas' ? :motivo_tomadas : :motivo_abonadas) end end
方案3:使用单个输入框,动态切换标签
只保留一个motivo输入框,通过JS切换类型时修改输入框的标签文本,从根源避免同名冲突:
视图修改:
<%= simple_form_for(@vacacion, validate: true, html: { class: "form-horizontal", role: "form" }) do |f| %> <%= f.error_notification %> <%= display_base_errors @vacacion %> <%= f.input :tipo, label: 'Tipo', as: :select, collection: [["Registrar días de vacaciones utilizados", "tomadas"], ["Abonar días de vacaciones", "abonadas"]], required: true %> <div id="id1" style="display:none"> <%= f.input :desde, label: 'Fecha inicio vacaciones', as: :datepicker, input_html: { value: @vacacion.desde.present? ? l(@vacacion.desde, format: :slash) : nil } %> <%= f.input :hasta, label: 'Fecha fin vacaciones', as: :datepicker, input_html: { value: @vacacion.hasta.present? ? l(@vacacion.hasta, format: :slash) : nil } %> <%= f.input :dias_tomados, label: 'Días de vacaciones utilizados', input_html: { min: 0 }, hint: '<div id="dias_habiles_div"></div>'.html_safe %> </div> <div id="id2" style="display:none"> <%= f.input :dias_abonados, label: 'Días de vacaciones a abonar', input_html: { min: 0 } %> </div> <%= f.input :motivo, input_html: { id: 'motivo_input' }, label: 'Motivo' %> <% end %>
JS修改:
$(document).ready(function(){ $("#vacacion_tipo").change(function(){ const tomadasDiv = $("#id1"); const abonadasDiv = $("#id2"); const motivoLabel = $("#motivo_input").closest(".form-group").find("label"); if(this.value == "tomadas"){ abonadasDiv.hide("slow"); tomadasDiv.show("slow"); motivoLabel.text("Motivo de los días tomados"); } if(this.value == "abonadas"){ tomadasDiv.hide("slow"); abonadasDiv.show("slow"); motivoLabel.text("Motivo de los días abonados"); } }); });
内容的提问来源于stack exchange,提问作者Rodrigo Ladrón de Guevara
相关产品推荐
相关产品推荐

