From 91db189af99b4c70623b99dbf0baa9831507eee5 Mon Sep 17 00:00:00 2001 From: Peter Yates Date: Tue, 16 Feb 2021 13:10:27 +0000 Subject: [PATCH 1/2] Add include_hidden option to check box collection This option defaults to true and allows developers to control whether or not a hidden field is injected into their collection of check boxes. Refs #238 --- .../builder.rb | 4 ++- .../elements/check_boxes/collection.rb | 25 ++++++++++--------- .../builder/check_boxes/collection_spec.rb | 12 +++++++++ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/lib/govuk_design_system_formbuilder/builder.rb b/lib/govuk_design_system_formbuilder/builder.rb index dc9b648b..c39ad416 100644 --- a/lib/govuk_design_system_formbuilder/builder.rb +++ b/lib/govuk_design_system_formbuilder/builder.rb @@ -646,6 +646,7 @@ def govuk_radio_divider(text = config.default_radio_divider_text) # @param form_group [Hash] configures the form group # @option form_group classes [Array,String] sets the form group's classes # @option form_group kwargs [Hash] additional attributes added to the form group + # @param include_hidden [Boolean] controls whether a hidden field is inserted to allow for empty submissions # @param block [Block] any HTML passed in will be injected into the fieldset, after the hint and before the checkboxes # @return [ActiveSupport::SafeBuffer] HTML output # @@ -682,7 +683,7 @@ def govuk_radio_divider(text = config.default_radio_divider_text) # :name, # legend: -> { tag.h3('What kind of sandwich do you want?') } # - def govuk_collection_check_boxes(attribute_name, collection, value_method, text_method, hint_method = nil, hint: {}, legend: {}, caption: {}, small: false, classes: nil, form_group: {}, &block) + def govuk_collection_check_boxes(attribute_name, collection, value_method, text_method, hint_method = nil, hint: {}, legend: {}, caption: {}, small: false, classes: nil, form_group: {}, include_hidden: true, &block) Elements::CheckBoxes::Collection.new( self, object_name, @@ -697,6 +698,7 @@ def govuk_collection_check_boxes(attribute_name, collection, value_method, text_ small: small, classes: classes, form_group: form_group, + include_hidden: include_hidden, &block ).html end diff --git a/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb b/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb index ca4a7ce1..ffe19506 100644 --- a/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +++ b/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb @@ -6,19 +6,20 @@ class Collection < Base include Traits::Hint include Traits::Supplemental - def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint:, legend:, caption:, small:, classes:, form_group:, hint_method: nil, &block) + def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint:, legend:, caption:, small:, classes:, form_group:, include_hidden:, hint_method: nil, &block) super(builder, object_name, attribute_name, &block) - @collection = collection - @value_method = value_method - @text_method = text_method - @hint_method = hint_method - @small = small - @legend = legend - @caption = caption - @hint = hint - @classes = classes - @form_group = form_group + @collection = collection + @value_method = value_method + @text_method = text_method + @hint_method = hint_method + @small = small + @legend = legend + @caption = caption + @hint = hint + @classes = classes + @form_group = form_group + @include_hidden = include_hidden end def html @@ -56,7 +57,7 @@ def check_boxes def collection link_errors = has_errors? - @builder.collection_check_boxes(@attribute_name, @collection, @value_method, @text_method) do |check_box| + @builder.collection_check_boxes(@attribute_name, @collection, @value_method, @text_method, include_hidden: @include_hidden) do |check_box| Elements::CheckBoxes::CollectionCheckBox.new( @builder, @object_name, diff --git a/spec/govuk_design_system_formbuilder/builder/check_boxes/collection_spec.rb b/spec/govuk_design_system_formbuilder/builder/check_boxes/collection_spec.rb index 5106883c..43889796 100644 --- a/spec/govuk_design_system_formbuilder/builder/check_boxes/collection_spec.rb +++ b/spec/govuk_design_system_formbuilder/builder/check_boxes/collection_spec.rb @@ -66,6 +66,10 @@ end end + specify 'a hidden field is present by default' do + expect(subject).to have_tag('input', with: { type: 'hidden', name: "#{object_name}[#{attribute}][]" }) + end + context 'check box size' do context 'when small is specified in the options' do subject { builder.send(*args, small: true) } @@ -156,6 +160,14 @@ it_behaves_like 'a collection field that supports setting the value via a proc' do let(:attribute) { :favourite_colour } end + + context 'suppressing the hidden field' do + subject { builder.send(*args, include_hidden: false) } + + specify "the hidden field should be present within the fieldset" do + expect(subject).not_to have_tag('input', with: { type: 'hidden' }) + end + end end end end From 9fc0a7ffad859f5a0b58e3264afc3ae0e3d2ddf7 Mon Sep 17 00:00:00 2001 From: Peter Yates Date: Tue, 16 Feb 2021 13:45:41 +0000 Subject: [PATCH 2/2] Add collection hidden fields configuration Now the default behaviour for collection fields, both radio and check box, can be set. For consistenty with Rails both default to true; this is a departure from the old behaviour of radio buttons defaulting to false. To maintain the old behaviour set: config.default_collection_radio_buttons_include_hidden = false Refs #238 --- lib/govuk_design_system_formbuilder.rb | 8 ++++++++ lib/govuk_design_system_formbuilder/builder.rb | 4 ++-- .../builder/error_summary_spec.rb | 2 +- .../builder/radios/collection_spec.rb | 10 +++++----- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/govuk_design_system_formbuilder.rb b/lib/govuk_design_system_formbuilder.rb index eca6743b..0442d42b 100644 --- a/lib/govuk_design_system_formbuilder.rb +++ b/lib/govuk_design_system_formbuilder.rb @@ -34,6 +34,12 @@ module GOVUKDesignSystemFormBuilder # blocks. As per the GOV.UK Design System spec, it defaults to # 'There is a problem'. # + # * +:default_collection_check_boxes_include_hidden+ controls whether or not + # a hidden field is added when rendering a collection of check boxes + # + # * +:default_collection_radio_buttons_include_hidden+ controls whether or not + # a hidden field is added when rendering a collection of radio buttons + # # * +:localisation_schema_fallback+ sets the prefix elements for the array # used to build the localisation string. The final two elements are always # are the object name and attribute name. The _special_ value +__context__+, @@ -52,6 +58,8 @@ module GOVUKDesignSystemFormBuilder default_submit_button_text: 'Continue', default_radio_divider_text: 'or', default_error_summary_title: 'There is a problem', + default_collection_check_boxes_include_hidden: true, + default_collection_radio_buttons_include_hidden: true, localisation_schema_fallback: %i(helpers __context__), localisation_schema_label: nil, diff --git a/lib/govuk_design_system_formbuilder/builder.rb b/lib/govuk_design_system_formbuilder/builder.rb index c39ad416..59a47842 100644 --- a/lib/govuk_design_system_formbuilder/builder.rb +++ b/lib/govuk_design_system_formbuilder/builder.rb @@ -501,7 +501,7 @@ def govuk_collection_select(attribute_name, collection, value_method, text_metho # :name, # legend: -> { tag.h3('Which category do you belong to?') } # - def govuk_collection_radio_buttons(attribute_name, collection, value_method, text_method = nil, hint_method = nil, hint: {}, legend: {}, caption: {}, inline: false, small: false, bold_labels: false, classes: nil, include_hidden: false, form_group: {}, &block) + def govuk_collection_radio_buttons(attribute_name, collection, value_method, text_method = nil, hint_method = nil, hint: {}, legend: {}, caption: {}, inline: false, small: false, bold_labels: false, classes: nil, include_hidden: config.default_collection_radio_buttons_include_hidden, form_group: {}, &block) Elements::Radios::Collection.new( self, object_name, @@ -683,7 +683,7 @@ def govuk_radio_divider(text = config.default_radio_divider_text) # :name, # legend: -> { tag.h3('What kind of sandwich do you want?') } # - def govuk_collection_check_boxes(attribute_name, collection, value_method, text_method, hint_method = nil, hint: {}, legend: {}, caption: {}, small: false, classes: nil, form_group: {}, include_hidden: true, &block) + def govuk_collection_check_boxes(attribute_name, collection, value_method, text_method, hint_method = nil, hint: {}, legend: {}, caption: {}, small: false, classes: nil, form_group: {}, include_hidden: config.default_collection_check_boxes_include_hidden, &block) Elements::CheckBoxes::Collection.new( self, object_name, diff --git a/spec/govuk_design_system_formbuilder/builder/error_summary_spec.rb b/spec/govuk_design_system_formbuilder/builder/error_summary_spec.rb index a6e8f5ee..fba21074 100644 --- a/spec/govuk_design_system_formbuilder/builder/error_summary_spec.rb +++ b/spec/govuk_design_system_formbuilder/builder/error_summary_spec.rb @@ -124,7 +124,7 @@ end specify 'the radio button linked to should be first' do - expect(parsed_subject.css('input').first['id']).to eql(identifier) + expect(parsed_subject.css('input[type="radio"]').first['id']).to eql(identifier) expect(parsed_subject.css('label').first['for']).to eql(identifier) end diff --git a/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb b/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb index e2c80686..8df2249a 100644 --- a/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb +++ b/spec/govuk_design_system_formbuilder/builder/radios/collection_spec.rb @@ -79,7 +79,9 @@ end specify %(shouldn't have a hidden field by default) do - expect(subject).not_to have_tag('input', with: { type: 'hidden' }) + expect(subject).to have_tag('fieldset') do + with_tag('input', with: { type: 'hidden', name: "#{object_name}[#{attribute}]" }) + end end specify 'each label should have the correct classes' do @@ -229,12 +231,10 @@ end context 'generating a hidden field' do - subject { builder.send(*args, include_hidden: true) } + subject { builder.send(*args, include_hidden: false) } specify "the hidden field should be present within the fieldset" do - expect(subject).to have_tag('fieldset') do - with_tag('input', with: { type: 'hidden', name: "#{object_name}[#{attribute}]" }) - end + expect(subject).not_to have_tag('input', with: { type: 'hidden' }) end end end