How to display checkbox and string fields like this image in a form?
I have a spectrum
boolean column and a spectrum_color
string column and I'd like to display the options to user as shown in this image. I'm using Tailwind CSS and the Jumpstart Pro Rails template so the visual side is easy, just not sure what form helpers to use to get the values from 3 radio buttons to fill one boolean field and a string field.
EDIT: can't get an image to display in this post. Here's a link: https://wmd.d.pr/AMZFsu
You can either:
- Add some code to the model to transform the selected value here to what you want in the attributes
before_validation
- Add Javascript to change hidden fields based upon the selection
I'd probably go with Javascript personally in this case as I think it'd be a little simpler.
Right, Javascript does sound like the better route. Would you hijack the form submit and set the values there? Or would you respond to changes on the radio button inputs as they happen then let the form submit normally?
I would use a Stimulus controller to listen for "change" event on the radios and then update the hidden fields accordingly.
Just in case anyone finds this helpful, here's how I solved this with Stimulus. If you see any improvements let me know!
# _form.html.erb
...
<div class="form-group" data-controller="filters">
<%= form.label "spectrum" %>
<%= radio_button_tag :spectrum, "none", :checked,
data: { "action": "click->filters#update" } %>
<%= label_tag :spectrum_none, "None" %>
<%= radio_button_tag :spectrum, "white", false,
data: { "action": "click->filters#update" } %>
<%= label_tag :spectrum_white, "White" %>
<%= radio_button_tag :spectrum, "black", false,
data: { "action": "click->filters#update" } %>
<%= label_tag :spectrum_black, "Black" %>
<%= form.hidden_field :spectrum,
data: { "target": "filters.spectrum" } %>
<%= form.hidden_field :spectrum_color,
data: { "target": "filters.spectrum_color" } %>
</div>
...
# app/javascripts/controllers/filters_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
update(event) {
const value = event.target.value
const spectrum = value == "none" ? false : true
const spectrum_color = value == "none" ? "" : value
this.targets.find("spectrum").value = spectrum
this.targets.find("spectrum_color").value = spectrum_color
}
}