You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Haml中根据单选按钮选中状态动态控制表单元素显隐

How to Show/Hide Form Elements Based on Radio Button Selection (Haml + CoffeeScript)

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: display first_name and last_name inputs
  • When any other option (like "company") is selected: hide those two inputs, switch the first_name label text to match the selected type, and clear the last_name value

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:

  1. Listens for the change event on the radio buttons
  2. Grabs the selected value
  3. Updates the first_name label using pre-stored data values
  4. Toggles the hidden class on the last_name field's parent container (assuming you have CSS that hides elements with this class)
  5. Clears the last_name input when switching to "company"
  6. Triggers the change event 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 of bind() (jQuery deprecated bind() in v3.0, and on() 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 .hidden class:
.hidden {
  display: none;
}
  • If you also want to hide the first_name field when not selecting "person" (instead of just changing its label), add this to the toggleNameFields function:
$firstNameGroup = $firstNameInput.parents('.fields-group')
$firstNameGroup.toggleClass('hidden', selectedValue != 'person')

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 21:57:30