govuk_design_system_formbuilder 2.5.3 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
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