govuk_design_system_formbuilder 0.7.9 → 0.7.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -18
- data/lib/govuk_design_system_formbuilder.rb +19 -4
- data/lib/govuk_design_system_formbuilder/base.rb +54 -17
- data/lib/govuk_design_system_formbuilder/builder.rb +147 -93
- data/lib/govuk_design_system_formbuilder/containers/check_boxes_fieldset.rb +28 -0
- data/lib/govuk_design_system_formbuilder/containers/fieldset.rb +3 -9
- data/lib/govuk_design_system_formbuilder/containers/radio_buttons_fieldset.rb +29 -0
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection.rb +62 -0
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/collection_check_box.rb +21 -7
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/fieldset_check_box.rb +75 -0
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/hint.rb +9 -17
- data/lib/govuk_design_system_formbuilder/elements/check_boxes/label.rb +5 -4
- data/lib/govuk_design_system_formbuilder/elements/date.rb +18 -14
- data/lib/govuk_design_system_formbuilder/elements/error_message.rb +6 -4
- data/lib/govuk_design_system_formbuilder/elements/error_summary.rb +23 -8
- data/lib/govuk_design_system_formbuilder/elements/file.rb +40 -0
- data/lib/govuk_design_system_formbuilder/elements/hint.rb +1 -1
- data/lib/govuk_design_system_formbuilder/elements/input.rb +4 -12
- data/lib/govuk_design_system_formbuilder/elements/label.rb +16 -6
- data/lib/govuk_design_system_formbuilder/elements/radios/collection.rb +55 -0
- data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio_button.rb +48 -0
- data/lib/govuk_design_system_formbuilder/elements/radios/{fieldset_radio.rb → fieldset_radio_button.rb} +17 -8
- data/lib/govuk_design_system_formbuilder/elements/select.rb +51 -0
- data/lib/govuk_design_system_formbuilder/elements/submit.rb +21 -13
- data/lib/govuk_design_system_formbuilder/elements/text_area.rb +4 -8
- data/lib/govuk_design_system_formbuilder/version.rb +1 -1
- metadata +32 -12
- data/lib/govuk_design_system_formbuilder/elements/radios/collection_radio.rb +0 -33
@@ -0,0 +1,28 @@
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
2
|
+
module Containers
|
3
|
+
class CheckBoxesFieldset < GOVUKDesignSystemFormBuilder::Base
|
4
|
+
def initialize(builder, object_name, attribute_name, hint_text:, legend:, small:, &block)
|
5
|
+
super(builder, object_name, attribute_name)
|
6
|
+
|
7
|
+
@legend = legend
|
8
|
+
@hint_text = hint_text
|
9
|
+
@small = small
|
10
|
+
@block_content = @builder.capture { block.call }
|
11
|
+
end
|
12
|
+
|
13
|
+
def html
|
14
|
+
Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
|
15
|
+
Containers::Fieldset.new(@builder, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
|
16
|
+
@builder.safe_join([
|
17
|
+
hint_element.html,
|
18
|
+
error_element.html,
|
19
|
+
Containers::CheckBoxes.new(@builder, small: @small).html do
|
20
|
+
@block_content
|
21
|
+
end
|
22
|
+
])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -7,7 +7,7 @@ module GOVUKDesignSystemFormBuilder
|
|
7
7
|
def initialize(builder, legend: {}, described_by: nil)
|
8
8
|
@builder = builder
|
9
9
|
@legend = LEGEND_DEFAULTS.merge(legend)
|
10
|
-
@described_by =
|
10
|
+
@described_by = described_by(described_by)
|
11
11
|
end
|
12
12
|
|
13
13
|
def html
|
@@ -35,20 +35,14 @@ module GOVUKDesignSystemFormBuilder
|
|
35
35
|
|
36
36
|
def legend_classes
|
37
37
|
size = @legend.dig(:size)
|
38
|
-
fail "invalid size #{size}, must be #{LEGEND_SIZES.join(', ')}" unless size.in?(LEGEND_SIZES)
|
38
|
+
fail "invalid size '#{size}', must be #{LEGEND_SIZES.join(', ')}" unless size.in?(LEGEND_SIZES)
|
39
39
|
|
40
|
-
"govuk-fieldset__legend govuk-fieldset__legend--#{size}"
|
40
|
+
["govuk-fieldset__legend", "govuk-fieldset__legend--#{size}"]
|
41
41
|
end
|
42
42
|
|
43
43
|
def legend_heading_classes
|
44
44
|
%(govuk-fieldset__heading)
|
45
45
|
end
|
46
|
-
|
47
|
-
def descriptors(described_by)
|
48
|
-
return nil unless described_by.present?
|
49
|
-
|
50
|
-
described_by.compact.join(' ').presence
|
51
|
-
end
|
52
46
|
end
|
53
47
|
end
|
54
48
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
2
|
+
module Containers
|
3
|
+
class RadioButtonsFieldset < GOVUKDesignSystemFormBuilder::Base
|
4
|
+
def initialize(builder, object_name, attribute_name, hint_text:, legend:, inline:, small:, &block)
|
5
|
+
super(builder, object_name, attribute_name)
|
6
|
+
|
7
|
+
@inline = inline
|
8
|
+
@small = small
|
9
|
+
@legend = legend
|
10
|
+
@hint_text = hint_text
|
11
|
+
@block_content = @builder.capture { block.call }
|
12
|
+
end
|
13
|
+
|
14
|
+
def html
|
15
|
+
Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
|
16
|
+
Containers::Fieldset.new(@builder, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
|
17
|
+
@builder.safe_join([
|
18
|
+
hint_element.html,
|
19
|
+
error_element.html,
|
20
|
+
Containers::Radios.new(@builder, inline: @inline, small: @small).html do
|
21
|
+
@block_content
|
22
|
+
end
|
23
|
+
])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
2
|
+
module Elements
|
3
|
+
module CheckBoxes
|
4
|
+
class Collection < GOVUKDesignSystemFormBuilder::Base
|
5
|
+
def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method: nil, hint_text:, legend:, small:, &block)
|
6
|
+
super(builder, object_name, attribute_name)
|
7
|
+
|
8
|
+
@collection = collection
|
9
|
+
@value_method = value_method
|
10
|
+
@text_method = text_method
|
11
|
+
@hint_method = hint_method
|
12
|
+
@small = small
|
13
|
+
@legend = legend
|
14
|
+
@hint_text = hint_text
|
15
|
+
@block_content = @builder.capture { block.call } if block_given?
|
16
|
+
end
|
17
|
+
|
18
|
+
def html
|
19
|
+
Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
|
20
|
+
Containers::Fieldset.new(@builder, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
|
21
|
+
@builder.safe_join(
|
22
|
+
[
|
23
|
+
hint_element.html,
|
24
|
+
error_element.html,
|
25
|
+
@block_content,
|
26
|
+
Containers::CheckBoxes.new(@builder, small: @small).html do
|
27
|
+
build_collection
|
28
|
+
end
|
29
|
+
]
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
# Builds a collection of check {Elements::CheckBoxes::CheckBox}
|
38
|
+
# @return [ActiveSupport::SafeBuffer] HTML output
|
39
|
+
#
|
40
|
+
# @note The GOV.UK design system requires that error summary links should
|
41
|
+
# link to the first checkbox directly. As we don't know if a collection will
|
42
|
+
# be rendered when it happens we need to work on the chance that it might, so
|
43
|
+
# the +link_errors+ variable is set to +true+ if this attribute has errors and
|
44
|
+
# always set back to +false+ after the first checkbox has been rendered
|
45
|
+
def build_collection
|
46
|
+
link_errors = has_errors?
|
47
|
+
|
48
|
+
@builder.collection_check_boxes(@attribute_name, @collection, @value_method, @text_method) do |check_box|
|
49
|
+
Elements::CheckBoxes::CollectionCheckBox.new(
|
50
|
+
@builder,
|
51
|
+
@object_name,
|
52
|
+
@attribute_name,
|
53
|
+
check_box,
|
54
|
+
@hint_method,
|
55
|
+
link_errors: link_errors
|
56
|
+
).html.tap { link_errors = false }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -2,26 +2,40 @@ module GOVUKDesignSystemFormBuilder
|
|
2
2
|
module Elements
|
3
3
|
module CheckBoxes
|
4
4
|
class CollectionCheckBox < GOVUKDesignSystemFormBuilder::Base
|
5
|
-
def initialize(builder,
|
6
|
-
|
7
|
-
@attribute = attribute
|
5
|
+
def initialize(builder, object_name, attribute_name, checkbox, hint_method = nil, link_errors: false)
|
6
|
+
super(builder, object_name, attribute_name)
|
8
7
|
@checkbox = checkbox
|
9
8
|
@item = checkbox.object
|
9
|
+
@value = checkbox.value
|
10
10
|
@hint_text = @item.send(hint_method) if hint_method.present?
|
11
|
+
@link_errors = link_errors
|
11
12
|
end
|
12
13
|
|
13
14
|
def html
|
14
|
-
hint = Hint.new(@builder, @attribute, @checkbox, @hint_text)
|
15
15
|
@builder.content_tag('div', class: 'govuk-checkboxes__item') do
|
16
16
|
@builder.safe_join(
|
17
17
|
[
|
18
|
-
@checkbox.check_box(
|
19
|
-
|
20
|
-
|
18
|
+
@checkbox.check_box(
|
19
|
+
id: field_id(link_errors: @link_errors),
|
20
|
+
class: "govuk-checkboxes__input",
|
21
|
+
aria: { describedby: hint_element.hint_id }
|
22
|
+
),
|
23
|
+
label_element.html,
|
24
|
+
hint_element.html
|
21
25
|
]
|
22
26
|
)
|
23
27
|
end
|
24
28
|
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def label_element
|
33
|
+
@label_element ||= Label.new(@checkbox, @object_name, @attribute_name, value: @value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def hint_element
|
37
|
+
@hint_element ||= Hint.new(@builder, @object_name, @attribute_name, @hint_text, value: @value)
|
38
|
+
end
|
25
39
|
end
|
26
40
|
end
|
27
41
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module GOVUKDesignSystemFormBuilder
|
2
|
+
module Elements
|
3
|
+
module CheckBoxes
|
4
|
+
class FieldsetCheckBox < GOVUKDesignSystemFormBuilder::Base
|
5
|
+
def initialize(builder, object_name, attribute_name, value, label:, hint_text:, link_errors:, multiple:, &block)
|
6
|
+
super(builder, object_name, attribute_name)
|
7
|
+
|
8
|
+
@value = value
|
9
|
+
@label = label
|
10
|
+
@hint_text = hint_text
|
11
|
+
@multiple = multiple
|
12
|
+
@link_errors = link_errors
|
13
|
+
|
14
|
+
if block_given?
|
15
|
+
@conditional_content = wrap_conditional(block)
|
16
|
+
@conditional_id = conditional_id
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def html
|
21
|
+
@builder.content_tag('div', class: 'govuk-checkboxes__item') do
|
22
|
+
@builder.safe_join([input, label, hint, @conditional_content])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def input
|
29
|
+
@builder.check_box(
|
30
|
+
@attribute_name,
|
31
|
+
{
|
32
|
+
id: field_id(link_errors: @link_errors),
|
33
|
+
class: check_box_classes,
|
34
|
+
multiple: @multiple,
|
35
|
+
aria: { describedby: hint_id },
|
36
|
+
data: { 'aria-controls' => @conditional_id }
|
37
|
+
},
|
38
|
+
@value,
|
39
|
+
false
|
40
|
+
)
|
41
|
+
end
|
42
|
+
|
43
|
+
def label
|
44
|
+
Elements::Label.new(
|
45
|
+
@builder,
|
46
|
+
@object_name,
|
47
|
+
@attribute_name,
|
48
|
+
value: @value,
|
49
|
+
checkbox: true,
|
50
|
+
**@label,
|
51
|
+
).html
|
52
|
+
end
|
53
|
+
|
54
|
+
def hint
|
55
|
+
Elements::Hint.new(
|
56
|
+
@builder,
|
57
|
+
@object_name,
|
58
|
+
@attribute_name,
|
59
|
+
@hint_text,
|
60
|
+
@value,
|
61
|
+
checkbox: true
|
62
|
+
).html
|
63
|
+
end
|
64
|
+
|
65
|
+
def conditional_classes
|
66
|
+
%w(govuk-checkboxes__conditional govuk-checkboxes__conditional--hidden)
|
67
|
+
end
|
68
|
+
|
69
|
+
def check_box_classes
|
70
|
+
%w(govuk-checkboxes__input)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -1,30 +1,22 @@
|
|
1
1
|
module GOVUKDesignSystemFormBuilder
|
2
2
|
module Elements
|
3
3
|
module CheckBoxes
|
4
|
-
class Hint
|
5
|
-
def initialize(builder,
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
@
|
4
|
+
class Hint < GOVUKDesignSystemFormBuilder::Base
|
5
|
+
def initialize(builder, object_name, attribute_name, hint_text, value:)
|
6
|
+
super(builder, object_name, attribute_name)
|
7
|
+
|
8
|
+
@value = value
|
9
|
+
@hint_text = hint_text
|
10
10
|
end
|
11
11
|
|
12
12
|
def html
|
13
|
-
return nil if @
|
13
|
+
return nil if @hint_text.blank?
|
14
14
|
|
15
|
-
@builder.tag.span(@
|
15
|
+
@builder.tag.span(@hint_text, class: hint_classes, id: id)
|
16
16
|
end
|
17
17
|
|
18
18
|
def id
|
19
|
-
|
20
|
-
|
21
|
-
[
|
22
|
-
@attribute,
|
23
|
-
@checkbox.object.id,
|
24
|
-
'hint'
|
25
|
-
]
|
26
|
-
.join('-')
|
27
|
-
.parameterize
|
19
|
+
hint_id
|
28
20
|
end
|
29
21
|
|
30
22
|
private
|
@@ -1,13 +1,14 @@
|
|
1
1
|
module GOVUKDesignSystemFormBuilder
|
2
2
|
module Elements
|
3
3
|
module CheckBoxes
|
4
|
-
class Label
|
5
|
-
def initialize(builder)
|
6
|
-
|
4
|
+
class Label < GOVUKDesignSystemFormBuilder::Base
|
5
|
+
def initialize(builder, object_name, attribute_name, value:)
|
6
|
+
super(builder, object_name, attribute_name)
|
7
|
+
@value = value
|
7
8
|
end
|
8
9
|
|
9
10
|
def html
|
10
|
-
@builder.label(class: label_classes)
|
11
|
+
@builder.label(for: field_id, class: label_classes)
|
11
12
|
end
|
12
13
|
|
13
14
|
private
|
@@ -8,13 +8,10 @@ module GOVUKDesignSystemFormBuilder
|
|
8
8
|
@legend = legend
|
9
9
|
@hint_text = hint_text
|
10
10
|
@date_of_birth = date_of_birth
|
11
|
-
@block_content = @builder.capture { block.call }
|
11
|
+
@block_content = @builder.capture { block.call } if block_given?
|
12
12
|
end
|
13
13
|
|
14
14
|
def html
|
15
|
-
hint_element = Elements::Hint.new(@builder, @object_name, @attribute_name, @hint_text)
|
16
|
-
error_element = Elements::ErrorMessage.new(@builder, @object_name, @attribute_name)
|
17
|
-
|
18
15
|
Containers::FormGroup.new(@builder, @object_name, @attribute_name).html do
|
19
16
|
Containers::Fieldset.new(@builder, legend: @legend, described_by: [error_element.error_id, hint_element.hint_id]).html do
|
20
17
|
@builder.safe_join(
|
@@ -25,9 +22,9 @@ module GOVUKDesignSystemFormBuilder
|
|
25
22
|
@builder.content_tag('div', class: 'govuk-date-input') do
|
26
23
|
@builder.safe_join(
|
27
24
|
[
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
date_input_item(:day, link_errors: true),
|
26
|
+
date_input_item(:month),
|
27
|
+
date_input_item(:year, width: 4)
|
31
28
|
]
|
32
29
|
)
|
33
30
|
end
|
@@ -39,7 +36,7 @@ module GOVUKDesignSystemFormBuilder
|
|
39
36
|
|
40
37
|
private
|
41
38
|
|
42
|
-
def
|
39
|
+
def date_input_item(segment, width: 2, link_errors: false)
|
43
40
|
value = @builder.object.try(@attribute_name).try(segment)
|
44
41
|
|
45
42
|
@builder.content_tag('div', class: %w(govuk-date-input__item)) do
|
@@ -49,13 +46,13 @@ module GOVUKDesignSystemFormBuilder
|
|
49
46
|
@builder.tag.label(
|
50
47
|
segment.capitalize,
|
51
48
|
class: date_input_label_classes,
|
52
|
-
for:
|
49
|
+
for: date_attribute_id(segment, link_errors)
|
53
50
|
),
|
54
51
|
|
55
52
|
@builder.tag.input(
|
56
|
-
id:
|
53
|
+
id: date_attribute_id(segment, link_errors),
|
57
54
|
class: date_input_classes(width),
|
58
|
-
name:
|
55
|
+
name: date_attribute_name(segment),
|
59
56
|
type: 'text',
|
60
57
|
pattern: '[0-9]*',
|
61
58
|
inputmode: 'numeric',
|
@@ -79,11 +76,18 @@ module GOVUKDesignSystemFormBuilder
|
|
79
76
|
%w(govuk-label govuk-date-input__label)
|
80
77
|
end
|
81
78
|
|
82
|
-
|
83
|
-
|
79
|
+
# if the field has errors we want the govuk_error_summary to
|
80
|
+
# be able to link to the day field. Otherwise, generate IDs
|
81
|
+
# in the normal fashion
|
82
|
+
def date_attribute_id(segment, link_errors)
|
83
|
+
if has_errors? && link_errors
|
84
|
+
field_id(link_errors: link_errors)
|
85
|
+
else
|
86
|
+
[@object_name, @attribute_name, SEGMENTS.fetch(segment)].join("_")
|
87
|
+
end
|
84
88
|
end
|
85
89
|
|
86
|
-
def
|
90
|
+
def date_attribute_name(segment)
|
87
91
|
"%<object_name>s[%<attribute_name>s(%<segment>s)]" % {
|
88
92
|
object_name: @object_name,
|
89
93
|
attribute_name: @attribute_name,
|
@@ -9,10 +9,12 @@ module GOVUKDesignSystemFormBuilder
|
|
9
9
|
return nil unless has_errors?
|
10
10
|
|
11
11
|
@builder.content_tag('span', class: 'govuk-error-message', id: error_id) do
|
12
|
-
@builder.safe_join(
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
@builder.safe_join(
|
13
|
+
[
|
14
|
+
@builder.tag.span('Error: ', class: 'govuk-visually-hidden'),
|
15
|
+
message
|
16
|
+
]
|
17
|
+
)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -10,12 +10,12 @@ module GOVUKDesignSystemFormBuilder
|
|
10
10
|
def html
|
11
11
|
return nil unless object_has_errors?
|
12
12
|
|
13
|
-
@builder.content_tag('div', class:
|
13
|
+
@builder.content_tag('div', class: summary_class, **error_summary_attributes) do
|
14
14
|
@builder.safe_join(
|
15
15
|
[
|
16
|
-
@builder.tag.h2(@title, id: error_summary_title_id, class: '
|
17
|
-
@builder.content_tag('div', class: '
|
18
|
-
@builder.content_tag('ul', class: 'govuk-list
|
16
|
+
@builder.tag.h2(@title, id: error_summary_title_id, class: summary_class('title')),
|
17
|
+
@builder.content_tag('div', class: summary_class('body')) do
|
18
|
+
@builder.content_tag('ul', class: ['govuk-list', summary_class('list')]) do
|
19
19
|
@builder.safe_join(
|
20
20
|
@builder.object.errors.messages.map do |attribute, messages|
|
21
21
|
error_list_item(attribute, messages)
|
@@ -32,15 +32,30 @@ module GOVUKDesignSystemFormBuilder
|
|
32
32
|
|
33
33
|
def error_list_item(attribute, messages)
|
34
34
|
@builder.content_tag('li') do
|
35
|
-
@builder.
|
35
|
+
@builder.link_to(
|
36
36
|
messages.join(', '),
|
37
|
-
|
37
|
+
same_page_link(field_id(attribute)),
|
38
|
+
data: {
|
39
|
+
turbolinks: false
|
40
|
+
}
|
38
41
|
)
|
39
42
|
end
|
40
43
|
end
|
41
44
|
|
42
|
-
def
|
43
|
-
|
45
|
+
def same_page_link(target)
|
46
|
+
'#'.concat(target)
|
47
|
+
end
|
48
|
+
|
49
|
+
def summary_class(part = nil)
|
50
|
+
if part
|
51
|
+
'govuk-error-summary'.concat('__', part)
|
52
|
+
else
|
53
|
+
'govuk-error-summary'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def field_id(attribute)
|
58
|
+
build_id('field-error', attribute_name: attribute)
|
44
59
|
end
|
45
60
|
|
46
61
|
def error_summary_title_id
|