Add optional hidden sentinel field for Primer’s checkbox groups. wp/74398

This commit is contained in:
David F
2026-04-30 11:10:28 +02:00
parent 79a182f62f
commit 68f3d335fa
4 changed files with 41 additions and 2 deletions
@@ -56,9 +56,9 @@ See COPYRIGHT and LICENSE files for more details.
input_width: :small
form.hidden(name: "settings[password_active_rules][]", value: "", scope_name_to_model: false)
form.check_box_group(name: :password_active_rules,
disabled:,
include_hidden: true,
label: I18n.t(:setting_password_active_rules)) do |group|
OpenProject::Passwords::Evaluator.known_rules.each do |value|
group.check_box(value:,
@@ -19,7 +19,8 @@ module Primer
super(**decorate_options(**), &)
end
def check_box_group(**, &)
def check_box_group(include_hidden: false, **, &)
add_input Primer::Forms::Dsl::HiddenInput.new(builder:, form:, multiple: true, value: "", **) if include_hidden
super(**decorate_options(**), &)
end
@@ -39,6 +39,22 @@ module OpenProject
def advanced_check_box_group
render_with_template
end
# `check_box_group` with `include_hidden: true`
#
# HTML forms do not submit unchecked checkboxes, so when every option in an
# array-valued `check_box_group` is unchecked, the field key is absent from
# the request params entirely. The server then has no way to distinguish
# "user cleared all selections" from "this field was not part of the form",
# and the previous value is silently preserved.
#
# Pass `include_hidden: true` to emit a hidden sentinel field before the
# checkboxes. This mirrors the behaviour of Rails' own `check_box` helper
# and ensures the key is always present in params — as an empty array when
# nothing is checked — so the server can save the empty selection correctly.
def check_box_group_with_include_hidden
render_with_template
end
end
end
end
@@ -0,0 +1,22 @@
<%
the_form = Class.new(ApplicationForm) do
form do |f|
f.check_box_group(name: :colors, include_hidden: true, label: "Favorite colors") do |group|
group.check_box(value: "red", label: "Red")
group.check_box(value: "green", label: "Green")
group.check_box(value: "blue", label: "Blue")
end
f.submit(name: "submit", label: "Save")
end
end
%>
<%=
primer_form_with(
url: "/abc",
method: :post
) do |f|
render(the_form.new(f))
end
%>