govuk_design_system_formbuilder 2.5.3 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/lib/govuk_design_system_formbuilder.rb +14 -0
  4. data/lib/govuk_design_system_formbuilder/base.rb +16 -16
  5. data/lib/govuk_design_system_formbuilder/builder.rb +27 -7
  6. data/lib/govuk_design_system_formbuilder/builder_helper.rb +65 -0
  7. data/lib/govuk_design_system_formbuilder/containers/check_boxes.rb +1 -1
  8. data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +2 -1
  9. data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +1 -1
  10. data/lib/govuk_design_system_formbuilder/containers/form_group.rb +1 -1
  11. data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +3 -2
  12. data/lib/govuk_design_system_formbuilder/containers/radios.rb +1 -1
  13. data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +11 -4
  14. data/lib/govuk_design_system_formbuilder/elements/collection_select.rb +1 -1
  15. data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +38 -9
  16. data/lib/govuk_design_system_formbuilder/elements/file.rb +1 -1
  17. data/lib/govuk_design_system_formbuilder/elements/inputs/number.rb +2 -0
  18. data/lib/govuk_design_system_formbuilder/elements/inputs/password.rb +2 -0
  19. data/lib/govuk_design_system_formbuilder/elements/inputs/phone.rb +2 -0
  20. data/lib/govuk_design_system_formbuilder/elements/inputs/text.rb +2 -0
  21. data/lib/govuk_design_system_formbuilder/elements/inputs/url.rb +2 -0
  22. data/lib/govuk_design_system_formbuilder/elements/radios/fieldset_radio_button.rb +2 -2
  23. data/lib/govuk_design_system_formbuilder/elements/select.rb +1 -1
  24. data/lib/govuk_design_system_formbuilder/elements/submit.rb +14 -2
  25. data/lib/govuk_design_system_formbuilder/elements/text_area.rb +1 -1
  26. data/lib/govuk_design_system_formbuilder/proxy.rb +13 -0
  27. data/lib/govuk_design_system_formbuilder/traits/fieldset_item.rb +4 -4
  28. data/lib/govuk_design_system_formbuilder/traits/input.rb +1 -1
  29. data/lib/govuk_design_system_formbuilder/traits/select.rb +1 -1
  30. data/lib/govuk_design_system_formbuilder/version.rb +1 -1
  31. metadata +10 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4dde3d10e811cb75c61423193a1f19acd4c3f55c9abc7cbc0a72cee8aab40fde
4
- data.tar.gz: f7e7eb253f038b1a392ee0c111c36a336649b2bfdaeb1c83a4e71018eaab2936
3
+ metadata.gz: 06a3aa374a6a6fa23d1fb52cdb7585fe50e067580328683b5dcbbcd8c6444aab
4
+ data.tar.gz: 15c814a5314cbf8aa97fd9e8d47c640062286d6a2239be89265015f6eafab172
5
5
  SHA512:
6
- metadata.gz: 8aeed919d9f6e25e6d2b70ebc16206ba7f41e72b86fe8ea20888ac6870bc81255f9ebb8c9ee7a3d6cebe0f067e0a5c13d3fbef5a46c3cfff9432a09c6967074b
7
- data.tar.gz: 16d556b230c3241c7f28c208a11eaf8bfa11634178dc52d8aa7f19c654271304acc6d3f1f916138a1fef66f1fa8c305fe48c2c6fe4e6ac41459b1777442059f7
6
+ metadata.gz: c4319d5fbd9168b1869aa94a1206f57c50f4e2d1a238a06da0bbcae0a55b82a020895ca1cfc59de86fdb9ee0248cbd283a3f5b22142946b9951a96906e870c9e
7
+ data.tar.gz: eec0ec045b248bd16cf671b4d289ea91429338693c541c74c30d92d481b2f2a833c490b064ed58bce7e95a49af03725faa6cb58b0222f0a5411153d1673d4a89
data/README.md CHANGED
@@ -7,9 +7,9 @@
7
7
  [![Test Coverage](https://api.codeclimate.com/v1/badges/fde73b5dc9476197281b/test_coverage)](https://codeclimate.com/github/DFE-Digital/govuk_design_system_formbuilder/test_coverage)
8
8
  [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=DFE-Digital/govuk_design_system_formbuilder)](https://dependabot.com)
9
9
  [![GitHub license](https://img.shields.io/github/license/DFE-Digital/govuk_design_system_formbuilder)](https://github.com/DFE-Digital/govuk_design_system_formbuilder/blob/master/LICENSE)
10
- [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-3.12.0-brightgreen)](https://design-system.service.gov.uk)
10
+ [![GOV.UK Design System Version](https://img.shields.io/badge/GOV.UK%20Design%20System-3.13.0-brightgreen)](https://design-system.service.gov.uk)
11
11
  [![Rails](https://img.shields.io/badge/Ruby-2.6.7%20%E2%95%B1%202.7.3%20%E2%95%B1%203.0.1-E16D6D)](https://www.ruby-lang.org/en/downloads/)
12
- [![Ruby](https://img.shields.io/badge/Rails-6.0.3.6%20%E2%95%B1%206.1.3.1-E16D6D)](https://weblog.rubyonrails.org/releases/)
12
+ [![Ruby](https://img.shields.io/badge/Rails-6.0.4%20%E2%95%B1%206.1.3.2-E16D6D)](https://weblog.rubyonrails.org/releases/)
13
13
 
14
14
  This library provides an easy-to-use form builder for the [GOV.UK Design System](https://design-system.service.gov.uk/).
15
15
 
@@ -27,6 +27,12 @@ module GOVUKDesignSystemFormBuilder
27
27
  # * +:default_submit_button_text+ sets the value assigned to +govuk_submit+,
28
28
  # defaults to 'Continue'.
29
29
  #
30
+ # * +:default_radio_divider_text+ sets the text automatically added to the
31
+ # radio button divider, defaults to 'or'
32
+ #
33
+ # * +:default_check_box_divider_text+ sets the text automatically added to the
34
+ # checkbox divider, defaults to 'or'
35
+ #
30
36
  # * +:default_submit_button_text+ sets the text used to divide the last radio
31
37
  # button in radio button fieldsets. As per the GOV.UK Design System spec,
32
38
  # it defaults to 'or'.
@@ -41,6 +47,10 @@ module GOVUKDesignSystemFormBuilder
41
47
  # * +:default_collection_radio_buttons_include_hidden+ controls whether or not
42
48
  # a hidden field is added when rendering a collection of radio buttons
43
49
  #
50
+ # * +:default_error_summary_error_order_method+ is the method that the library
51
+ # will check for on the bound object to see whether or not to try ordering the
52
+ # error messages
53
+ #
44
54
  # * +:localisation_schema_fallback+ sets the prefix elements for the array
45
55
  # used to build the localisation string. The final two elements are always
46
56
  # are the object name and attribute name. The _special_ value +__context__+,
@@ -61,7 +71,9 @@ module GOVUKDesignSystemFormBuilder
61
71
  default_caption_size: 'm',
62
72
  default_submit_button_text: 'Continue',
63
73
  default_radio_divider_text: 'or',
74
+ default_check_box_divider_text: 'or',
64
75
  default_error_summary_title: 'There is a problem',
76
+ default_error_summary_error_order_method: nil,
65
77
  default_collection_check_boxes_include_hidden: true,
66
78
  default_collection_radio_buttons_include_hidden: true,
67
79
  default_submit_validate: false,
@@ -108,6 +120,8 @@ module GOVUKDesignSystemFormBuilder
108
120
  include GOVUKDesignSystemFormBuilder::Builder
109
121
  end
110
122
 
123
+ class FormBuilderProxy < FormBuilder; end
124
+
111
125
  # Disable Rails' div.field_with_error wrapper
112
126
  ActionView::Base.field_error_proc = ->(html_tag, _instance) { html_tag }
113
127
  end
@@ -15,21 +15,6 @@ module GOVUKDesignSystemFormBuilder
15
15
  html || ''
16
16
  end
17
17
 
18
- private
19
-
20
- # returns the attributes bound to the object that are
21
- # required to build all contained elements
22
- #
23
- # @return [GOVUKDesignSystemFormBuilder::FormBuilder, Symbol, Symbol] an array containing the
24
- # builder, object name and attribute name
25
- def bound
26
- [@builder, @object_name, @attribute_name]
27
- end
28
-
29
- def brand(override = nil)
30
- override || config.brand
31
- end
32
-
33
18
  # returns the id value used for the input
34
19
  #
35
20
  # @note field_id is overridden so that the error summary can link to the
@@ -51,13 +36,28 @@ module GOVUKDesignSystemFormBuilder
51
36
  end
52
37
  end
53
38
 
39
+ private
40
+
41
+ # returns the attributes bound to the object that are
42
+ # required to build all contained elements
43
+ #
44
+ # @return [GOVUKDesignSystemFormBuilder::FormBuilder, Symbol, Symbol] an array containing the
45
+ # builder, object name and attribute name
46
+ def bound
47
+ [@builder, @object_name, @attribute_name]
48
+ end
49
+
50
+ def brand(override = nil)
51
+ override || config.brand
52
+ end
53
+
54
54
  def has_errors?
55
55
  @builder.object.respond_to?(:errors) &&
56
56
  @builder.object.errors.any? &&
57
57
  @builder.object.errors.messages[@attribute_name].present?
58
58
  end
59
59
 
60
- def described_by(*ids)
60
+ def combine_references(*ids)
61
61
  ids.flatten.compact
62
62
  end
63
63
 
@@ -813,6 +813,8 @@ module GOVUKDesignSystemFormBuilder
813
813
  # @option label hidden [Boolean] control the visability of the label. Hidden labels will stil be read by screenreaders
814
814
  # @option label kwargs [Hash] additional arguments are applied as attributes on the +label+ element
815
815
  # @param multiple [Boolean] controls whether the check box is part of a collection or represents a single attribute
816
+ # @param exclusive [Boolean] sets the checkbox so that when checked none of its siblings can be too. Usually
817
+ # used for the 'None of these apply to me' option found beneath a {#govuk_check_box_divider}.
816
818
  # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the +input+ element
817
819
  # @param block [Block] any HTML passed in will form the contents of the fieldset
818
820
  # @return [ActiveSupport::SafeBuffer] HTML output
@@ -825,7 +827,7 @@ module GOVUKDesignSystemFormBuilder
825
827
  # label: { text: 'Do you agree with our terms and conditions?' },
826
828
  # hint: { text: 'You will not be able to proceed unless you do' }
827
829
  #
828
- def govuk_check_box(attribute_name, value, unchecked_value = false, hint: {}, label: {}, link_errors: false, multiple: true, **kwargs, &block)
830
+ def govuk_check_box(attribute_name, value, unchecked_value = false, hint: {}, label: {}, link_errors: false, multiple: true, exclusive: false, **kwargs, &block)
829
831
  Elements::CheckBoxes::FieldsetCheckBox.new(
830
832
  self,
831
833
  object_name,
@@ -836,14 +838,27 @@ module GOVUKDesignSystemFormBuilder
836
838
  label: label,
837
839
  link_errors: link_errors,
838
840
  multiple: multiple,
841
+ exclusive: exclusive,
839
842
  **kwargs,
840
843
  &block
841
844
  ).html
842
845
  end
843
846
 
847
+ # Inserts a text divider into a list of check boxes
848
+ #
849
+ # @param text [String] The divider text
850
+ # @note This should only be used from within a {#govuk_check_boxes_fieldset}
851
+ # @see https://design-system.service.gov.uk/components/checkboxes/#add-an-option-for-none- GOV.UK check boxes with a text divider
852
+ # @return [ActiveSupport::SafeBuffer] HTML output
853
+ # @example A custom divider
854
+ # = govuk_check_box_divider 'On the other hand'
855
+ def govuk_check_box_divider(text = config.default_check_box_divider_text)
856
+ tag.div(text, class: %w(govuk-checkboxes__divider))
857
+ end
858
+
844
859
  # Generates a submit button, green by default
845
860
  #
846
- # @param text [String] the button text
861
+ # @param text [String,Proc] the button text. When a +Proc+ is provided its contents will be rendered within the button element
847
862
  # @param warning [Boolean] makes the button red ({https://design-system.service.gov.uk/components/button/#warning-buttons warning}) when true
848
863
  # @param secondary [Boolean] makes the button grey ({https://design-system.service.gov.uk/components/button/#secondary-buttons secondary}) when true
849
864
  # @param classes [Array,String] Classes to add to the submit button
@@ -853,7 +868,7 @@ module GOVUKDesignSystemFormBuilder
853
868
  # client-side validation provided by the browser. This is to provide a more consistent and accessible user
854
869
  # experience
855
870
  # @param disabled [Boolean] makes the button disabled when true
856
- # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the +input+ element
871
+ # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the +button+ element
857
872
  # @param block [Block] When content is passed in via a block the submit element and the block content will
858
873
  # be wrapped in a +<div class="govuk-button-group">+ which will space the buttons and links within
859
874
  # evenly.
@@ -861,8 +876,9 @@ module GOVUKDesignSystemFormBuilder
861
876
  # @return [ActiveSupport::SafeBuffer] HTML output
862
877
  # @note Only the first additional button or link (passed in via a block) will be given the
863
878
  # correct left margin, subsequent buttons will need to be manually accounted for
864
- # @note This helper always renders an +<input type='submit'>+ tag, HTML content is not supported inside. You
865
- # can place +<button>+ tags inside the form to have the same effect
879
+ # @note This helper always renders an +<button type='submit'>+ tag. Previous versions of this gem rendered
880
+ # a +`<input type='submit'>' tag instead, but there is a {https://github.com/alphagov/govuk_elements/issues/545 longstanding bug}
881
+ # with this approach where the top few pixels don't initiate a submission when clicked.
866
882
  # @see https://design-system.service.gov.uk/components/button/#stop-users-from-accidentally-sending-information-more-than-once
867
883
  # GOV.UK double click prevention
868
884
  #
@@ -930,7 +946,11 @@ module GOVUKDesignSystemFormBuilder
930
946
  # @param title [String] the error summary heading
931
947
  # @param link_base_errors_to [Symbol,String] set the field that errors on +:base+ are linked
932
948
  # to, as there won't be a field representing the object base.
949
+ # @param order [Array<Symbol>] the attribute order in which error messages are displayed. Ordered
950
+ # attributes will appear first and unordered ones will be last, sorted in the default manner (in
951
+ # which they were defined on the model).
933
952
  # @option kwargs [Hash] kwargs additional arguments are applied as attributes to the error summary +div+ element
953
+ # @param block [Block] arbitrary HTML that will be rendered between title and error message list
934
954
  #
935
955
  # @note Only the first error in the +#errors+ array for each attribute will
936
956
  # be included.
@@ -939,8 +959,8 @@ module GOVUKDesignSystemFormBuilder
939
959
  # = f.govuk_error_summary 'Uh-oh, spaghettios'
940
960
  #
941
961
  # @see https://design-system.service.gov.uk/components/error-summary/ GOV.UK error summary
942
- def govuk_error_summary(title = config.default_error_summary_title, link_base_errors_to: nil, **kwargs)
943
- Elements::ErrorSummary.new(self, object_name, title, link_base_errors_to: link_base_errors_to, **kwargs).html
962
+ def govuk_error_summary(title = config.default_error_summary_title, link_base_errors_to: nil, order: nil, **kwargs, &block)
963
+ Elements::ErrorSummary.new(self, object_name, title, link_base_errors_to: link_base_errors_to, order: order, **kwargs, &block).html
944
964
  end
945
965
 
946
966
  # Generates a fieldset containing the contents of the block
@@ -0,0 +1,65 @@
1
+ module GOVUKDesignSystemFormBuilder
2
+ # NOTE: this is currently considered experimental, it's likely to change based on feedback.
3
+ #
4
+ # BuilderHelper contains methods that expose the form builder's functionality
5
+ # externally. The objectives are to allow:
6
+ #
7
+ # * rendering the error summary outside of the form
8
+ #
9
+ # * setting the id of custom form elements (rich text editors, date pickers,
10
+ # sliders, etc) using the formbuilder's internal logic, allowing them to be
11
+ # linked from the error summary
12
+ module BuilderHelper
13
+ # Returns the form builder generated id for an object's attribute, allowing
14
+ # users to force their custom element ids to match those that'll be generated
15
+ # by the error summary.
16
+ # @param object [ActiveRecord::Base,ActiveModel::Model,Object] the object that we want to
17
+ # generate an id for
18
+ # @param object_name [Symbol] the object's name, the singular version of the object's class
19
+ # name, e.g., +Person+ is +:person+.
20
+ # @param attribute_name [Symbol] the attribute we're generating an id for
21
+ # @param value [Object] the value of the attribute. Only necessary for fields with
22
+ # multiple form elements like radio buttons and checkboxes
23
+ # @param link_errors [Boolean] toggles whether or not to override the field id with the
24
+ # error id when there are errors on the +object+. Only relevant for radio buttons
25
+ # and check boxes.
26
+ def govuk_field_id(object, attribute_name, object_name = nil, value: nil, link_errors: true)
27
+ (object_name = retrieve_object_name(object)) if object_name.nil?
28
+
29
+ proxy_base(object, object_name, attribute_name, value: value).field_id(link_errors: link_errors)
30
+ end
31
+
32
+ # Renders an error summary
33
+ # @param object [ActiveRecord::Base,ActiveModel::Model,Object] the object we'll be rendering
34
+ # the errors for
35
+ # @param object_name [Symbol] the object's name, the singular version of the object's class
36
+ # name, e.g., +Person+ is +:person+. If none is supplied we'll try to infer it from
37
+ # the object, so it'll probably be necessary for regular Ruby objects
38
+ # @option args [Array] options passed through to the builder's +#govuk_error_summary+
39
+ # @option kwargs [Hash] keyword options passed through to the builder's +#govuk_error_summary+
40
+ #
41
+ # @example
42
+ # = govuk_error_summary(@registration)
43
+ #
44
+ # @see https://design-system.service.gov.uk/components/error-summary/ GOV.UK error summary
45
+ def govuk_error_summary(object, object_name = nil, *args, **kwargs, &block)
46
+ (object_name = retrieve_object_name(object)) if object_name.nil?
47
+
48
+ proxy_builder(object, object_name, self, {}).govuk_error_summary(*args, **kwargs, &block)
49
+ end
50
+
51
+ private
52
+
53
+ def proxy_base(object, object_name, attribute_name, value: nil)
54
+ GOVUKDesignSystemFormBuilder::Proxy.new(object, object_name, attribute_name, value: value)
55
+ end
56
+
57
+ def proxy_builder(object, object_name, template, options)
58
+ GOVUKDesignSystemFormBuilder::FormBuilderProxy.new(object_name, object, template, options)
59
+ end
60
+
61
+ def retrieve_object_name(object)
62
+ object.to_model.model_name.singular
63
+ end
64
+ end
65
+ end
@@ -22,7 +22,7 @@ module GOVUKDesignSystemFormBuilder
22
22
  end
23
23
 
24
24
  def classes
25
- [%(#{brand}-checkboxes), small_class, custom_classes].flatten.compact
25
+ combine_references(%(#{brand}-checkboxes), small_class, custom_classes)
26
26
  end
27
27
 
28
28
  def small_class
@@ -5,6 +5,8 @@ module GOVUKDesignSystemFormBuilder
5
5
  include Traits::Hint
6
6
 
7
7
  def initialize(builder, object_name, attribute_name, hint:, legend:, caption:, small:, classes:, form_group:, multiple:, &block)
8
+ fail LocalJumpError, 'no block given' unless block_given?
9
+
8
10
  super(builder, object_name, attribute_name, &block)
9
11
 
10
12
  @legend = legend
@@ -14,7 +16,6 @@ module GOVUKDesignSystemFormBuilder
14
16
  @classes = classes
15
17
  @form_group = form_group
16
18
  @multiple = multiple
17
- @block_content = capture { block.call }
18
19
  end
19
20
 
20
21
  def html
@@ -8,7 +8,7 @@ module GOVUKDesignSystemFormBuilder
8
8
 
9
9
  @legend = legend
10
10
  @caption = caption
11
- @described_by = described_by(described_by)
11
+ @described_by = combine_references(described_by)
12
12
  @attribute_name = attribute_name
13
13
  @html_attributes = kwargs
14
14
  end
@@ -15,7 +15,7 @@ module GOVUKDesignSystemFormBuilder
15
15
  private
16
16
 
17
17
  def classes
18
- [form_group_class, error_class, custom_classes].flatten.compact
18
+ combine_references(form_group_class, error_class, custom_classes)
19
19
  end
20
20
 
21
21
  def form_group_class
@@ -5,7 +5,9 @@ module GOVUKDesignSystemFormBuilder
5
5
  include Traits::Error
6
6
 
7
7
  def initialize(builder, object_name, attribute_name, hint:, legend:, caption:, inline:, small:, classes:, form_group:, &block)
8
- super(builder, object_name, attribute_name)
8
+ fail LocalJumpError, 'no block given' unless block_given?
9
+
10
+ super(builder, object_name, attribute_name, &block)
9
11
 
10
12
  @inline = inline
11
13
  @small = small
@@ -14,7 +16,6 @@ module GOVUKDesignSystemFormBuilder
14
16
  @hint = hint
15
17
  @classes = classes
16
18
  @form_group = form_group
17
- @block_content = capture { block.call }
18
19
  end
19
20
 
20
21
  def html
@@ -25,7 +25,7 @@ module GOVUKDesignSystemFormBuilder
25
25
  end
26
26
 
27
27
  def classes
28
- [%(#{brand}-radios), inline_class, small_class, custom_classes].flatten.compact
28
+ combine_references(%(#{brand}-radios), inline_class, small_class, custom_classes)
29
29
  end
30
30
 
31
31
  def inline_class
@@ -7,8 +7,8 @@ module GOVUKDesignSystemFormBuilder
7
7
  include Traits::HTMLAttributes
8
8
  include Traits::FieldsetItem
9
9
 
10
- def initialize(builder, object_name, attribute_name, value, unchecked_value, label:, hint:, link_errors:, multiple:, **kwargs, &block)
11
- super(builder, object_name, attribute_name)
10
+ def initialize(builder, object_name, attribute_name, value, unchecked_value, label:, hint:, link_errors:, multiple:, exclusive:, **kwargs, &block)
11
+ super(builder, object_name, attribute_name, &block)
12
12
 
13
13
  @value = value
14
14
  @unchecked_value = unchecked_value
@@ -17,8 +17,9 @@ module GOVUKDesignSystemFormBuilder
17
17
  @multiple = multiple
18
18
  @link_errors = link_errors
19
19
  @html_attributes = kwargs
20
+ @exclusive = exclusive
20
21
 
21
- conditional_content(&block)
22
+ conditional_content(@block_content)
22
23
  end
23
24
 
24
25
  private
@@ -28,12 +29,18 @@ module GOVUKDesignSystemFormBuilder
28
29
  end
29
30
 
30
31
  def input
31
- @builder.check_box(@attribute_name, attributes(@html_attributes), @value, @unchecked_value)
32
+ @builder.check_box(@attribute_name, attributes(@html_attributes.deep_merge(exclusive_options)), @value, @unchecked_value)
32
33
  end
33
34
 
34
35
  def fieldset_options
35
36
  { checkbox: true }
36
37
  end
38
+
39
+ def exclusive_options
40
+ return {} unless @exclusive
41
+
42
+ { data: { behaviour: 'exclusive' } }
43
+ end
37
44
  end
38
45
  end
39
46
  end
@@ -40,7 +40,7 @@ module GOVUKDesignSystemFormBuilder
40
40
  {
41
41
  id: field_id(link_errors: true),
42
42
  class: classes,
43
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
43
+ aria: { describedby: combine_references(hint_id, error_id, supplemental_id) }
44
44
  }
45
45
  end
46
46
 
@@ -4,12 +4,13 @@ module GOVUKDesignSystemFormBuilder
4
4
  include Traits::Error
5
5
  include Traits::HTMLAttributes
6
6
 
7
- def initialize(builder, object_name, title, link_base_errors_to:, **kwargs)
8
- super(builder, object_name, nil)
7
+ def initialize(builder, object_name, title, link_base_errors_to:, order:, **kwargs, &block)
8
+ super(builder, object_name, nil, &block)
9
9
 
10
10
  @title = title
11
11
  @link_base_errors_to = link_base_errors_to
12
12
  @html_attributes = kwargs
13
+ @order = order
13
14
  end
14
15
 
15
16
  def html
@@ -27,17 +28,45 @@ module GOVUKDesignSystemFormBuilder
27
28
  end
28
29
 
29
30
  def summary
30
- tag.div(class: summary_class('body')) do
31
- tag.ul(class: [%(#{brand}-list), summary_class('list')]) do
32
- safe_join(list)
33
- end
34
- end
31
+ tag.div(class: summary_class('body')) { safe_join([@block_content, list]) }
35
32
  end
36
33
 
37
34
  def list
38
- @builder.object.errors.messages.map do |attribute, messages|
39
- list_item(attribute, messages.first)
35
+ tag.ul(class: [%(#{brand}-list), summary_class('list')]) do
36
+ safe_join(error_messages.map { |attribute, messages| list_item(attribute, messages.first) })
37
+ end
38
+ end
39
+
40
+ def error_messages
41
+ messages = @builder.object.errors.messages
42
+
43
+ if reorder_errors?
44
+ adjustment = error_order.size + messages.size
45
+
46
+ return messages.sort_by.with_index do |(attr, _val), i|
47
+ error_order.index(attr) || (i + adjustment)
48
+ end
40
49
  end
50
+
51
+ @builder.object.errors.messages
52
+ end
53
+
54
+ def reorder_errors?
55
+ object = @builder.object
56
+
57
+ @order || (error_order_method &&
58
+ object.respond_to?(error_order_method) &&
59
+ object.send(error_order_method).present?)
60
+ end
61
+
62
+ def error_order
63
+ @order || @builder.object.send(config.default_error_summary_error_order_method)
64
+ end
65
+
66
+ # this method will be called on the bound object to see if custom error ordering
67
+ # has been enabled
68
+ def error_order_method
69
+ config.default_error_summary_error_order_method
41
70
  end
42
71
 
43
72
  def list_item(attribute, message)
@@ -35,7 +35,7 @@ module GOVUKDesignSystemFormBuilder
35
35
  {
36
36
  id: field_id(link_errors: true),
37
37
  class: classes,
38
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
38
+ aria: { describedby: combine_references(hint_id, error_id, supplemental_id) }
39
39
  }
40
40
  end
41
41
 
@@ -9,6 +9,8 @@ module GOVUKDesignSystemFormBuilder
9
9
  include Traits::Supplemental
10
10
  include Traits::HTMLAttributes
11
11
 
12
+ private
13
+
12
14
  def builder_method
13
15
  :number_field
14
16
  end
@@ -9,6 +9,8 @@ module GOVUKDesignSystemFormBuilder
9
9
  include Traits::Supplemental
10
10
  include Traits::HTMLAttributes
11
11
 
12
+ private
13
+
12
14
  def builder_method
13
15
  :password_field
14
16
  end
@@ -9,6 +9,8 @@ module GOVUKDesignSystemFormBuilder
9
9
  include Traits::Supplemental
10
10
  include Traits::HTMLAttributes
11
11
 
12
+ private
13
+
12
14
  def builder_method
13
15
  :phone_field
14
16
  end
@@ -9,6 +9,8 @@ module GOVUKDesignSystemFormBuilder
9
9
  include Traits::Supplemental
10
10
  include Traits::HTMLAttributes
11
11
 
12
+ private
13
+
12
14
  def builder_method
13
15
  :text_field
14
16
  end
@@ -9,6 +9,8 @@ module GOVUKDesignSystemFormBuilder
9
9
  include Traits::Supplemental
10
10
  include Traits::HTMLAttributes
11
11
 
12
+ private
13
+
12
14
  def builder_method
13
15
  :url_field
14
16
  end
@@ -8,7 +8,7 @@ module GOVUKDesignSystemFormBuilder
8
8
  include Traits::FieldsetItem
9
9
 
10
10
  def initialize(builder, object_name, attribute_name, value, label:, hint:, link_errors:, **kwargs, &block)
11
- super(builder, object_name, attribute_name)
11
+ super(builder, object_name, attribute_name, &block)
12
12
 
13
13
  @value = value
14
14
  @label = label
@@ -16,7 +16,7 @@ module GOVUKDesignSystemFormBuilder
16
16
  @link_errors = has_errors? && link_errors
17
17
  @html_attributes = kwargs
18
18
 
19
- conditional_content(&block)
19
+ conditional_content(@block_content)
20
20
  end
21
21
 
22
22
  private
@@ -38,7 +38,7 @@ module GOVUKDesignSystemFormBuilder
38
38
  {
39
39
  id: field_id(link_errors: true),
40
40
  class: classes,
41
- aria: { describedby: described_by(hint_id, error_id) }
41
+ aria: { describedby: combine_references(hint_id, error_id) }
42
42
  }
43
43
  end
44
44
  end
@@ -9,7 +9,7 @@ module GOVUKDesignSystemFormBuilder
9
9
 
10
10
  fail ArgumentError, 'buttons can be warning or secondary' if warning && secondary
11
11
 
12
- @text = text
12
+ @text = build_text(text)
13
13
  @prevent_double_click = prevent_double_click
14
14
  @warning = warning
15
15
  @secondary = secondary
@@ -26,6 +26,17 @@ module GOVUKDesignSystemFormBuilder
26
26
 
27
27
  private
28
28
 
29
+ def build_text(text)
30
+ case text
31
+ when String
32
+ text
33
+ when Proc
34
+ capture { text.call }
35
+ else
36
+ fail(ArgumentError, %(text must be a String or Proc))
37
+ end
38
+ end
39
+
29
40
  def button_group
30
41
  Containers::ButtonGroup.new(@builder, buttons).html
31
42
  end
@@ -35,11 +46,12 @@ module GOVUKDesignSystemFormBuilder
35
46
  end
36
47
 
37
48
  def submit
38
- @builder.submit(@text, **attributes(@html_attributes))
49
+ @builder.tag.button(@text, **attributes(@html_attributes))
39
50
  end
40
51
 
41
52
  def options
42
53
  {
54
+ type: 'submit',
43
55
  formnovalidate: !@validate,
44
56
  disabled: @disabled,
45
57
  class: classes,
@@ -53,7 +53,7 @@ module GOVUKDesignSystemFormBuilder
53
53
  id: field_id(link_errors: true),
54
54
  class: classes,
55
55
  rows: @rows,
56
- aria: { describedby: described_by(hint_id, error_id, supplemental_id, limit_description_id) },
56
+ aria: { describedby: combine_references(hint_id, error_id, supplemental_id, limit_description_id) },
57
57
  }
58
58
  end
59
59
 
@@ -0,0 +1,13 @@
1
+ require_relative 'base'
2
+
3
+ module GOVUKDesignSystemFormBuilder
4
+ class Proxy < GOVUKDesignSystemFormBuilder::Base
5
+ NullBuilder = Struct.new(:object)
6
+
7
+ def initialize(object, object_name, attribute_name, value: nil)
8
+ super(NullBuilder.new(object), object_name, attribute_name)
9
+
10
+ @value = value
11
+ end
12
+ end
13
+ end
@@ -4,7 +4,7 @@ module GOVUKDesignSystemFormBuilder
4
4
  using PrefixableArray
5
5
 
6
6
  def html
7
- safe_join([item, @conditional])
7
+ safe_join([item, @conditional_content])
8
8
  end
9
9
 
10
10
  private
@@ -61,9 +61,9 @@ module GOVUKDesignSystemFormBuilder
61
61
  build_id('conditional')
62
62
  end
63
63
 
64
- def conditional_content(&block)
65
- if (conditional_block_content = block_given? && (capture { block.call }).presence)
66
- @conditional = conditional_container(conditional_block_content)
64
+ def conditional_content(block_content)
65
+ if block_content.present?
66
+ @conditional_content = conditional_container(block_content)
67
67
  @conditional_id = conditional_id
68
68
  end
69
69
  end
@@ -48,7 +48,7 @@ module GOVUKDesignSystemFormBuilder
48
48
  {
49
49
  id: field_id(link_errors: true),
50
50
  class: classes,
51
- aria: { describedby: described_by(hint_id, error_id, supplemental_id) }
51
+ aria: { describedby: combine_references(hint_id, error_id, supplemental_id) }
52
52
  }
53
53
  end
54
54
 
@@ -4,7 +4,7 @@ module GOVUKDesignSystemFormBuilder
4
4
  private
5
5
 
6
6
  def classes
7
- [%(#{brand}-select), error_class].flatten.compact
7
+ combine_references(%(#{brand}-select), error_class)
8
8
  end
9
9
 
10
10
  def error_class
@@ -1,3 +1,3 @@
1
1
  module GOVUKDesignSystemFormBuilder
2
- VERSION = '2.5.3'.freeze
2
+ VERSION = '2.7.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govuk_design_system_formbuilder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.3
4
+ version: 2.7.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Yates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-04 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_merge
@@ -28,62 +28,44 @@ dependencies:
28
28
  name: actionview
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: 6.1.3.1
34
31
  - - ">="
35
32
  - !ruby/object:Gem::Version
36
- version: '6.1'
33
+ version: '6.0'
37
34
  type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
37
  requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: 6.1.3.1
44
38
  - - ">="
45
39
  - !ruby/object:Gem::Version
46
- version: '6.1'
40
+ version: '6.0'
47
41
  - !ruby/object:Gem::Dependency
48
42
  name: activemodel
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: 6.1.3.1
54
45
  - - ">="
55
46
  - !ruby/object:Gem::Version
56
- version: '6.1'
47
+ version: '6.0'
57
48
  type: :runtime
58
49
  prerelease: false
59
50
  version_requirements: !ruby/object:Gem::Requirement
60
51
  requirements:
61
- - - "~>"
62
- - !ruby/object:Gem::Version
63
- version: 6.1.3.1
64
52
  - - ">="
65
53
  - !ruby/object:Gem::Version
66
- version: '6.1'
54
+ version: '6.0'
67
55
  - !ruby/object:Gem::Dependency
68
56
  name: activesupport
69
57
  requirement: !ruby/object:Gem::Requirement
70
58
  requirements:
71
- - - "~>"
72
- - !ruby/object:Gem::Version
73
- version: 6.1.3.1
74
59
  - - ">="
75
60
  - !ruby/object:Gem::Version
76
- version: '6.1'
61
+ version: '6.0'
77
62
  type: :runtime
78
63
  prerelease: false
79
64
  version_requirements: !ruby/object:Gem::Requirement
80
65
  requirements:
81
- - - "~>"
82
- - !ruby/object:Gem::Version
83
- version: 6.1.3.1
84
66
  - - ">="
85
67
  - !ruby/object:Gem::Version
86
- version: '6.1'
68
+ version: '6.0'
87
69
  - !ruby/object:Gem::Dependency
88
70
  name: rubocop-govuk
89
71
  requirement: !ruby/object:Gem::Requirement
@@ -313,6 +295,7 @@ files:
313
295
  - lib/govuk_design_system_formbuilder.rb
314
296
  - lib/govuk_design_system_formbuilder/base.rb
315
297
  - lib/govuk_design_system_formbuilder/builder.rb
298
+ - lib/govuk_design_system_formbuilder/builder_helper.rb
316
299
  - lib/govuk_design_system_formbuilder/containers/button_group.rb
317
300
  - lib/govuk_design_system_formbuilder/containers/character_count.rb
318
301
  - lib/govuk_design_system_formbuilder/containers/check_boxes.rb
@@ -348,6 +331,7 @@ files:
348
331
  - lib/govuk_design_system_formbuilder/elements/select.rb
349
332
  - lib/govuk_design_system_formbuilder/elements/submit.rb
350
333
  - lib/govuk_design_system_formbuilder/elements/text_area.rb
334
+ - lib/govuk_design_system_formbuilder/proxy.rb
351
335
  - lib/govuk_design_system_formbuilder/refinements/prefixable_array.rb
352
336
  - lib/govuk_design_system_formbuilder/traits/caption.rb
353
337
  - lib/govuk_design_system_formbuilder/traits/collection_item.rb