Closed tstatter closed 8 months ago
I didn't get this far yet in the gem, but it's definitely something I want to include in the core library for a 1.0 release. If you'd be interested in building this out and including it in this gem I'd be happy to work through a PR with you and give you an overview of how this could be componentized.
I think the API would look something like (being lazy and making this a one-liner):
render field(:collection_point).select { CollectionPoint.all { |cp| option(value: cp.id) { cp.name } }
This would stay "as close to the HTML and Phlex" as possible (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select) if the select
block is a Phlex tag that renders a bunch of option
tags within it.
I'd also add that this could be shortened for ActiveRecord associations to just this:
render field(:collection_point).select.options(items: CollectionPoint.all) { |cp| cp.name }
Not sure about that exact method name and API, but the idea here is that you can pass select_associated
an ActiveRecord association so it can reflect on the ID of that record. I'd add that later since the most important thing for this library is exposing form helpers as closely to HTML and Phlex as possible, then adding syntactic sugar like this on top.
Ok cool, I think I have a working component so will raise PR asap
I have created a branch, but cannot push to it. Do you prefer I fork it, then raise PR in the fork ?
Fork and PR is fine! 👍
I started an implementation of this at https://github.com//rubymonolith/demo/blob/c3c221e4fdaac7b3c8082defdb6d4f25ebdee081/app/views/application_form.rb#L10-L24
So far it looks like this:
class Form < ApplicationForm
def template
labeled(field(:blog_id).select do |s|
s.options(Blog.pluck(:id, :title))
s.blank_option
end)
labeled field(:title).input.focus
labeled field(:publish_at).input
labeled field(:content).textarea(rows: 6)
submit
end
end
Syntax is still a bit awkward, but it does work. One thing I don't like is how the s.options
call takes an array and makes assumptions from it. A better API design that I'll explore is one that doesn't need an array for this to work.
I haven't released this gem yet, but the following example derived from the original post would work in main
:
render field(:collection_point).select CollectionPoint.select(:id, :name), nil
I started populating more advanced examples in the README at https://github.com/rubymonolith/superform#form-field-guide. Here's what it looks like if you get crazy with your select form and want to do something like grouped inputs:
div do
render field(:source).label { "How did you hear about us?" }
render field(:source).select do |s|
# Pretend WebSources is an ActiveRecord scope with a "Social" category that has "Facebook, X, etc"
# and a "Search" category with "AltaVista, Yahoo, etc."
WebSources.select(:id, :name).group_by(:category) do |category, sources|
s.optgroup(label: category) do
s.options(sources)
end
end
end
end
There's intentionally a lot of boilerplate in that example — its expected that people would reduce that with component extraction or by adding helper methods to the form class.
To add a drop down for collection_select in old form
Is there already a component for this or do we need to create a custom one ?
I tried a few variations such as (type: :select), no errors raised, but seems to always render a normal text input box e.g
Thanks