如何在Haml中根据单选按钮选中状态动态控制表单元素显隐
Hey there! Let's walk through refining your form behavior to match your needs—showing the first_name and last_name fields only when the "person" radio button is selected, and hiding them otherwise. Your existing code is already on the right track, so let's break it down and polish it a bit.
Your Requirements Recap
- When the radio button for
account.kind == "person"is selected: displayfirst_nameandlast_nameinputs - When any other option (like "company") is selected: hide those two inputs, switch the
first_namelabel text to match the selected type, and clear thelast_namevalue
Your Current Code Breakdown
Haml Form Markup
= simple_form_for(@account, html: { class: 'edit-form edit_account' }, wrapper: :edit_form) do |f| %fieldset.large-2-col %legend.hint %span= t('views.accounts.profile.description') .fields-block = f.input :kind, as: :radio_buttons, wrapper_class: 'fields-group contact-type', item_wrapper_class: 'inline', item_wrapper_tag: 'div', collection: Account.kind.options, required: true, wrapper: :inline_radio = f.input :first_name, autofocus: true, input_html: { data: { person: Account.human_attribute_name('first_name'), company: Account.human_attribute_name('company_name') } } = f.input :last_name
This setup is solid: you're using Simple Form to render the radio group, and storing dynamic label text for first_name in data attributes—smart move, since it keeps your text localized and easy to swap.
CoffeeScript Interaction
$"form input[name='account[kind]']".bind 'change', () -> selected_value = $"input[name='account[kind]']:checked".val() $"label[for='account_first_name']".html $('#account_first_name').data(selected_value) $"#account_last_name".parents('.fields-group').toggleClass('hidden', selected_value != 'person') $"#account_last_name".val('') if selected_value == 'company' false $"input[name='account[kind]']".trigger 'change' if $"input[name='account[kind]']".length > 0
Your logic here is spot-on for meeting the requirements:
- Listens for the
changeevent on the radio buttons - Grabs the selected value
- Updates the
first_namelabel using pre-storeddatavalues - Toggles the
hiddenclass on thelast_namefield's parent container (assuming you have CSS that hides elements with this class) - Clears the
last_nameinput when switching to "company" - Triggers the
changeevent on page load to set the initial state correctly
Quick Optimizations for Robustness
To make this code cleaner, faster, and future-proof, here are a few tweaks:
- Use
on()instead ofbind()(jQuery deprecatedbind()in v3.0, andon()is the preferred method for event binding) - Cache DOM elements to avoid repeated queries (this boosts performance, especially on larger forms)
- Wrap everything in a DOM-ready handler to ensure it runs only after the page is fully loaded
Here's the refined CoffeeScript:
$ -> # Cache DOM elements once instead of querying multiple times $kindRadios = $("form input[name='account[kind]']") $firstNameLabel = $("label[for='account_first_name']") $firstNameInput = $('#account_first_name') $lastNameGroup = $("#account_last_name").parents('.fields-group') $lastNameInput = $('#account_last_name') # Extract the toggle logic into a reusable function toggleNameFields = -> selectedValue = $kindRadios.filter(':checked').val() # Update first name label text $firstNameLabel.html $firstNameInput.data(selectedValue) # Show/hide last name field $lastNameGroup.toggleClass('hidden', selectedValue != 'person') # Clear last name if switching to company $lastNameInput.val('') if selectedValue == 'company' # Bind the change event $kindRadios.on 'change', toggleNameFields # Set initial state on page load toggleNameFields() if $kindRadios.length > 0
Key Notes to Ensure It Works
- Make sure your CSS includes the
.hiddenclass:
.hidden { display: none; }
- If you also want to hide the
first_namefield when not selecting "person" (instead of just changing its label), add this to thetoggleNameFieldsfunction:
$firstNameGroup = $firstNameInput.parents('.fields-group') $firstNameGroup.toggleClass('hidden', selectedValue != 'person')
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

