Module: Layered::Ui::FormHelper
- Defined in:
- app/helpers/layered/ui/form_helper.rb
Constant Summary collapse
- FIELD_TYPES =
%i[ string text email password number tel url search date datetime time month week color range file select checkbox hidden combobox ].freeze
Instance Method Summary collapse
-
#l_ui_field_describedby(record, attribute, hint: false) ⇒ Object
Space-joined ids for a field's aria-describedby: its hint (when the field has one) followed by its error message, which is always rendered.
- #l_ui_field_error_id(record, attribute) ⇒ Object
- #l_ui_field_hint_id(record, attribute) ⇒ Object
-
#l_ui_field_value(record, attribute) ⇒ Object
The record's current value for a field, used as the default selection for a :combobox field when
selected:is not given. -
#l_ui_form(record, fields:, url:, method: nil, submit: nil, multipart: nil) ⇒ Object
Renders a complete form with all fields, error summary, and submit button.
-
#l_ui_normalise_field(record, config) ⇒ Object
Normalises a raw field config hash into a canonical form.
Instance Method Details
#l_ui_field_describedby(record, attribute, hint: false) ⇒ Object
Space-joined ids for a field's aria-describedby: its hint (when the field has one) followed by its error message, which is always rendered.
116 117 118 119 120 121 |
# File 'app/helpers/layered/ui/form_helper.rb', line 116 def l_ui_field_describedby(record, attribute, hint: false) ids = [] ids << l_ui_field_hint_id(record, attribute) if hint ids << l_ui_field_error_id(record, attribute) ids.join(" ") end |
#l_ui_field_error_id(record, attribute) ⇒ Object
106 107 108 |
# File 'app/helpers/layered/ui/form_helper.rb', line 106 def l_ui_field_error_id(record, attribute) "#{record.model_name.param_key}_#{attribute}_error" end |
#l_ui_field_hint_id(record, attribute) ⇒ Object
110 111 112 |
# File 'app/helpers/layered/ui/form_helper.rb', line 110 def l_ui_field_hint_id(record, attribute) "#{record.model_name.param_key}_#{attribute}_hint" end |
#l_ui_field_value(record, attribute) ⇒ Object
The record's current value for a field, used as the default selection
for a :combobox field when selected: is not given.
102 103 104 |
# File 'app/helpers/layered/ui/form_helper.rb', line 102 def l_ui_field_value(record, attribute) record.public_send(attribute) if record.respond_to?(attribute) end |
#l_ui_form(record, fields:, url:, method: nil, submit: nil, multipart: nil) ⇒ Object
Renders a complete form with all fields, error summary, and submit button.
l_ui_form(@post,
fields: Post.l_managed_resource_fields,
url: managed_posts_path)
18 19 20 21 22 |
# File 'app/helpers/layered/ui/form_helper.rb', line 18 def l_ui_form(record, fields:, url:, method: nil, submit: nil, multipart: nil) render partial: "layered/ui/managed_resource/form", locals: { record: record, fields: fields, url: url, method: method, submit: submit, multipart: multipart } end |
#l_ui_normalise_field(record, config) ⇒ Object
Normalises a raw field config hash into a canonical form.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'app/helpers/layered/ui/form_helper.rb', line 25 def l_ui_normalise_field(record, config) attribute = config[:attribute] as = config[:as] || l_ui_field_type_for(record.class, attribute) unless FIELD_TYPES.include?(as) raise ArgumentError, "Unsupported field type :#{as} for :#{attribute}. " \ "Supported types: #{FIELD_TYPES.map { |t| ":#{t}" }.join(', ')}" end if as == :select && config[:collection].nil? raise ArgumentError, "Field :#{attribute} is declared as :select but has no :collection. " \ "Provide collection: [['Label', value], ...] or collection: -> { Model.pluck(:name, :id) }" end if as == :combobox && config[:collection].nil? && config[:url].nil? raise ArgumentError, "Field :#{attribute} is declared as :combobox but has no :collection or :url. " \ "Provide collection: [['Label', value], ...] to filter in the browser, " \ "or url: to fetch options from an endpoint as the user types" end if as == :combobox && config[:url] && !config.key?(:selected) && l_ui_field_value(record, attribute).present? raise ArgumentError, "Field :#{attribute} is a remote :combobox with a value already set, but no :selected. " \ "A remote collection cannot be searched for the label of an existing value, " \ "so pass it with its label, e.g. selected: [[record.user.name, record.user_id]]" end label = config[:label] || attribute.to_s.humanize extras = config.except(:attribute, :as, :label, :required, :hint, :collection, :placeholder, :prompt, :include_blank) if as == :combobox unusable = { prompt: "Use placeholder: instead, which a combobox shows until something is selected.", include_blank: "A combobox with no selection is already blank, so there is nothing to set." } unusable.each do |key, advice| next unless config.key?(key) raise ArgumentError, "Field :#{attribute} is a :combobox and cannot take :#{key}. #{advice}" end extras[:multiple] = l_ui_field_multiple?(record, attribute) unless config.key?(:multiple) allowed = ComboboxHelper::COMBOBOX_OPTIONS + [:class] unknown = extras.keys - allowed if unknown.any? raise ArgumentError, "Field :#{attribute} is a :combobox and cannot take " \ "#{unknown.map { |key| ":#{key}" }.join(', ')}. Unlike the other field types, a " \ "combobox takes only its own options (#{allowed.map { |key| ":#{key}" }.join(', ')}); " \ "extra HTML attributes belong on container:" end end { attribute: attribute, as: as, label: label, required: config.fetch(:required, false), hint: config[:hint], collection: config[:collection], placeholder: config[:placeholder], prompt: config[:prompt], include_blank: config[:include_blank], extras: extras } end |