Skip to content

Conversation

@nimmolo
Copy link

@nimmolo nimmolo commented Nov 13, 2025

This is a reboot of PR #33. It intends to support the multiple HTML spec for <select> elements.

# Multiple select with automatic [] appending and hidden input
field(:tag_ids).select(
  [1, "Ruby"], [2, "Rails"], [3, "Phlex"],
  multiple: true
)
# Renders: <input type="hidden" name="tag_ids[]" value="">
#          <select name="tag_ids[]" multiple>...</select>
  • Handles a multiple kwarg to the select method. Full backwards compatibility with the current API of select.
  • Field naming: names the select multiple field correctly — i.e., using square brackets in a way that does not interfere with parent field notation. (It has to prevent double [] when multiple select is used inside collections.) See this conversation. Tests all permutations I could think of.
  • Adds hidden field when multiple, to handle the way browsers handle blank selects (form value may not be submitted unless hidden field present)
  • Renames the internal Select component param for the array of options from collection to options (to avoid confusion with .collection method, which creates FieldCollections). Backwards compatible, both keywords accepted.
  • Adds tests for generated HTML.
  • Updates the README with examples of the new select API. Also updates the rest of the README with consistent syntax (field vs Field)
  • Updates the GEMSPEC to require Ruby 2.7, since the Superform codebase already uses anonymous arg forwarding all over the place (so it already effectively requires 2.7).

Note, I realize you proposed a separate multiple_select component method [in the discussion here] (#33 (comment)) and mentioned that also below, but I would suggest this is not really necessary or desirable, since the current PR maintains backwards compatibility with the current method signature. Keeping the select logic in one component seems to be the most intuitive and elegant way. In the select HTML element spec, multiple is just an attribute, not a separate element.

@nimmolo nimmolo changed the title Add multiple and include_blank keywords to select Add multiple and include_blank keywords to select Nov 13, 2025
@nimmolo
Copy link
Author

nimmolo commented Nov 14, 2025

more details:

Multiple select support
# Multiple select with automatic [] appending and hidden input
field(:tag_ids).select(
  [1, "Ruby"], [2, "Rails"], [3, "Phlex"],
  multiple: true
)
# Renders: <input type="hidden" name="tag_ids[]" value="">
#          <select name="tag_ids[]" multiple>...</select>
Include blank option
# Add blank option at the start
field(:country).select(
  nil, [1, "USA"], [2, "Canada"], [3, "Mexico"]
)
API harmonized with with radio component PR #65
# Positional arguments
field(:role_id).select([1, 'Admin'], [2, 'Editor'], [3, 'Viewer'])

# ActiveRecord relations (wrapped in array)
field(:author_id).select(User.select(:id, :name))

Notes

Multiple select handling
  • Array value detection (line 50): Array(field.value).include?(key) works for both single and multiple
  • Smart field naming (lines 74-78): Appends [] unless already in Field collection
  • Hidden input (lines 32-35): Ensures empty submissions send a value
  • Collection support: Handles user[orders][0][tag_ids][] correctly
Field naming logic
# Single select
name="role_id"

# Multiple select
name="role_ids[]"

# Multiple select in collection
name="user[orders][0][tag_ids][]"

# Multiple select in Field collection (parent is Field)
name="users[][]"  # No extra [] appended

Form integration tests

Integration tests to confirm Select works correctly in Rails forms:

Single Select
  • Field naming in collections: user[orders][0][item_id]
  • Pre-selection: Options correctly selected based on model values
  • Form submission cycle: Values round-trip correctly
Multiple Select
  • Array value handling: [1, 3] correctly selects multiple options
  • Field naming: user[orders][0][tag_ids][] with hidden inputs
  • Form submission cycle: Array values round-trip correctly
  • Empty submissions: Hidden input ensures params are sent

@bradgessler
Copy link
Contributor

Feedback is similar to the radio buttons PR

Eliminate the options keyword argument. Positional arguments handle this.

Eliminate the include_blank argument. A nil can be passed into the positional argument to achieve that via Field(:items).select(nil, *items). If this isn't clear, you might update the docs.

Similar to Field(:blah).radio().buttons.each vs Field(:blah).radio_buttons.each, we might separate out select_multiple with its own method like Field(:blah).select_multiple. I'm preferring the latter since it's very straight forward to explain to somebody verbally or in docs "Hey, if you want to select multiple, you'll have to call Field(:foo).select_multipleand it doesn't conflict with theselect` input method.

@nimmolo
Copy link
Author

nimmolo commented Nov 19, 2025

PR updated to reflect feedback.

Question (also asked on #65, but relevant here)

In Select currently, the field(:foo).select method seems to accept the "options" either as positional args, or sent under the kwarg "collection".

# undocumented kwarg on main
field(:foo).select(collection: [[1, 'Admin'], [2, 'Editor']])

# positional  
field(:foo).select([1, 'Admin'], [2, 'Editor'])

Is this kwarg available just because of the way it's initialized? Or is this considered a feature undocumented in the README? Maybe nobody uses it, can add a deprecation notice if passed directly.

@nimmolo nimmolo changed the title Add multiple and include_blank keywords to select Add multiple keyword/functionality to select Nov 19, 2025
@nimmolo
Copy link
Author

nimmolo commented Nov 25, 2025

An unexpected API gotcha i'm sure you're aware of:

Superform select uses [value, label] ordering for select options, which is the opposite of Rails' options_for_select [label, value].

This is a real gotcha for refactoring from ERB, it means devs have to manually flip all the arrays. It would be good to change this API. I can't imagine how to change it without breaking people's existing select implementations, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants