Created
March 13, 2020 17:45
-
-
Save tahb/79f2457c0f05fe07c47841e2eda694a4 to your computer and use it in GitHub Desktop.
WIP extending govuk form builder so radio inputs support checked defaults
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rails.application.config.action_view.default_form_builder = GOVUKDesignSystemFormBuilder::FormBuilder | |
# Don't use XHR when submitting forms | |
Rails.application.config.action_view.form_with_generates_remote_forms = false | |
# Use activerecord.attributes.model.attribute_name for label scope | |
module GOVUKDesignSystemFormBuilder | |
module Builder | |
def govuk_collection_radio_buttons(attribute_name, collection, value_method, text_method, hint_method = nil, hint_text: nil, legend: {}, inline: false, small: false, bold_labels: false, checked: false, classes: nil, &block) | |
Elements::Radios::Collection.new( | |
self, | |
object_name, | |
attribute_name, | |
collection, | |
value_method: value_method, | |
text_method: text_method, | |
hint_method: hint_method, | |
hint_text: hint_text, | |
legend: legend, | |
inline: inline, | |
small: small, | |
bold_labels: bold_labels, | |
classes: classes, | |
checked: checked, | |
&block | |
).html | |
end | |
end | |
class Base | |
private def localised_text(context) | |
key = localisation_key(context) | |
return nil unless I18n.exists?(key) | |
translation = I18n.translate(key) | |
translation = translation.fetch(:html).html_safe if translation.is_a?(Hash) && translation.key?(:html) | |
translation | |
end | |
private def localisation_key(context) | |
return nil unless @object_name.present? && @attribute_name.present? | |
if context == "label" | |
["activerecord", "attributes", @object_name, @attribute_name].join(".") | |
else | |
["helpers", context, @object_name, @attribute_name].join(".") | |
end | |
end | |
def has_errors? | |
@builder.object.errors.any? && | |
@builder.object.errors.messages.dig( | |
translated_attribute_name(attribute_name: @attribute_name) | |
).present? | |
end | |
# In order to support associations where the model association is | |
# eg. `provider` but the form attribute needs to be `provider_id`. | |
# The form field must be wrapped in errors and be linkable from the summary. | |
# | |
# 1. We cannot change the form field to `provider` since the value will | |
# not read from an object with a value already set. | |
# | |
# 2. We cannot change the model association to be `provider_id` as calling | |
# `transaction.provider_id` rather than the resource `transaction.provider` | |
# would be unconventional and also require a hack. | |
# | |
# 3. We cannot overwride the @attribute_name on create since that will have | |
# the same affect as point 1. | |
private def translated_attribute_name(attribute_name:) | |
translations = @builder.object.class.try("::FORM_FIELD_TRANSLATIONS") || {} | |
if translations[attribute_name].present? | |
translations[attribute_name] | |
else | |
attribute_name | |
end | |
end | |
end | |
end | |
module GOVUKDesignSystemFormBuilder | |
module Elements | |
class Select < GOVUKDesignSystemFormBuilder::Base | |
def error_element | |
@error_element ||= Elements::ErrorMessage.new( | |
@builder, | |
@object_name, | |
translated_attribute_name(attribute_name: @attribute_name) | |
) | |
end | |
def field_id(link_errors: false) | |
if link_errors && has_errors? | |
build_id( | |
"field-error", | |
include_value: false, | |
attribute_name: translated_attribute_name(attribute_name: @attribute_name) | |
) | |
else | |
build_id("field") | |
end | |
end | |
end | |
module Radios | |
def initialize(builder, object_name, attribute_name, collection, value_method:, text_method:, hint_method:, hint_text:, legend:, inline:, small:, bold_labels:, checked: false, classes:, &block) | |
super(builder, object_name, attribute_name, &block) | |
@collection = collection | |
@value_method = value_method | |
@text_method = text_method | |
@hint_method = hint_method | |
@inline = inline | |
@small = small | |
@legend = legend | |
@hint_text = hint_text | |
@classes = classes | |
@bold_labels = hint_method.present? || bold_labels | |
@checked = checked | |
end | |
class CollectionRadioButton < GOVUKDesignSystemFormBuilder::Base | |
def initialize(builder, object_name, attribute_name, item, value_method:, text_method:, hint_method:, link_errors: false, bold_labels:, checked: false) | |
super(builder, object_name, attribute_name) | |
@item = item | |
@value = retrieve(item, value_method) | |
@label_text = retrieve(item, text_method) | |
@hint_text = retrieve(item, hint_method) | |
@link_errors = link_errors | |
@bold_labels = bold_labels | |
@checked = checked | |
end | |
def retrieve(item, method) | |
case method | |
when Symbol, String | |
item.send(method) | |
when Proc | |
method.call(item) | |
end | |
end | |
def html | |
content_tag('div', class: 'govuk-radios__item') do | |
safe_join( | |
[ | |
@builder.radio_button( | |
@attribute_name, | |
@value, | |
id: field_id(link_errors: @link_errors), | |
aria: { describedby: hint_id }, | |
class: %w(govuk-radios__input), | |
checked: @checked, | |
), | |
label_element.html, | |
hint_element.html | |
] | |
) | |
end | |
end | |
def field_id(link_errors: false) | |
if link_errors && has_errors? | |
build_id( | |
"field-error", | |
include_value: false, | |
attribute_name: translated_attribute_name(attribute_name: @attribute_name) | |
) | |
else | |
build_id("field") | |
end | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment