Class: Forms::CheckboxGroup
- Inherits:
-
Phlex::HTML
- Object
- Phlex::HTML
- Forms::CheckboxGroup
- Defined in:
- lib/forms/checkbox_group.rb
Overview
A batched checkbox group for an array-valued field (the tag/facet-picker
shape). Renders a set of checkboxes sharing ONE array-valued field name
(user[tag_ids][]), with a leading empty-array hidden field so an empty
selection still submits, and derives each box's checked state from the
resolved value: of its item against the model's current set.
f.checkbox_group(:tag_ids, Tag.all, value: :id,
item_label: ->(t) { t.name.presence || t.slug }, variant: :pill, size: :sm)
The item value/text accessors (value:/label:/item_label:) live on the BUILDER (Forms::Field#checkbox_group), which pre-resolves each item to { value:, label:, checked:, id: } before this leaf renders. This leaf is presentation-only — it receives the resolved options: array, never the raw accessors. variant: :stack (default) | :inline | :pill — layout only, zero JS size: daisyUI checkbox size modifier (:xs :sm :md :lg :xl)
Accessible name (issue #17): role="group" needs one so a screen reader
announces the group when focus enters a checkbox. The leaf does NOT invent
its own naming API — extra attributes pass straight through to the group
div, so the caller names it with plain HTML/ARIA:
f.checkbox_group(:tag_ids, Tag.all, value: :id, aria: { label: "Tags" })
f.checkbox_group(:tag_ids, Tag.all, value: :id, aria: { labelledby: "hdr" })
Through f.field, the builder points the group at the Control's own visible
The checked set is passed in pre-resolved by the builder (Field#checkbox_group matches the model's current value by each item's resolved value:), so the component itself stays presentation-only. Each checkbox's markup is delegated to DaisyUI::Checkbox so its size class is a literal, scanner-visible token.
Direct Known Subclasses
Constant Summary collapse
- VARIANT_CLASSES =
variant -> the container class. The pill variant uses Tailwind's
has-[:checked]:to style the active label with no JS. { stack: "flex flex-col gap-2", inline: "flex flex-wrap gap-4", pill: "flex flex-wrap gap-2" }.freeze
Instance Method Summary collapse
-
#initialize(name:, id:, options:, variant: :stack, size: nil, error: false, **attributes) ⇒ CheckboxGroup
constructor
A new instance of CheckboxGroup.
- #view_template ⇒ Object
Constructor Details
#initialize(name:, id:, options:, variant: :stack, size: nil, error: false, **attributes) ⇒ CheckboxGroup
Returns a new instance of CheckboxGroup.
46 47 48 49 50 51 52 53 54 55 |
# File 'lib/forms/checkbox_group.rb', line 46 def initialize(name:, id:, options:, variant: :stack, size: nil, error: false, **attributes) @name = name # already the array name: "user[tag_ids][]" @id = id @options = # [{ value:, label:, checked:, id: }, ...] @variant = variant @size = size @error = error @attributes = attributes super() end |
Instance Method Details
#view_template ⇒ Object
57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/forms/checkbox_group.rb', line 57 def view_template # Empty-array hidden field so an empty selection still submits (the same # convention as collection_check_boxes). input(type: "hidden", name: @name, value: "") # class is the per-checkbox styling seam (see render_checkbox), not a group # attribute — everything else the caller passed lands on the group so aria:, # data:, id: etc. pass straight through. div(class: group_classes, role: "group", "aria-invalid": @error || nil, **@attributes.except(:class)) do @options.each { |option| item(option) } end end |