【问题标题】:Rails 4 form: conditional display of fields based on radio button selectionRails 4 form:基于单选按钮选择的字段条件显示
【发布时间】:2016-01-15 19:21:42
【问题描述】:

首先,如果这个问题是愚蠢的,请原谅,我刚刚开始研究 Rails,Javascript 和 jQuery 对我来说是一个全新的世界。

我发现了以下类似的问题,但只是不明白它们如何适用于我的情况:

话虽如此,这是我的问题。

在我的 Rails 4 应用程序中,我有以下 Rails 表单(我使用简单表单):

<div class="calendar_details">
  <%= f.label :target_relationship %>
  <%= radio_button_tag(:target_relationship, "B2C", :checked => true, :onclick=>"showMe('calendar_details_b2c')", {:class => "radio_button_target_relationship_b2C"}) %>
  <%= label_tag(:target_relationship, "B2C") %>
  <%= radio_button_tag(:target_relationship, "B2B", :onclick=>"showMe('calendar_details_b2b')", {:class => "radio_button_target_relationship_b2b"}) %>
  <%= label_tag(:target_relationship, "B2B") %>
</div>

<div class="calendar_details">
  <%= f.label :target_country %><%= f.country_select :target_country, ["United States"] %>
</div>

<div id="calendar_details_b2c">

  <div class="calendar_details">
  <%= f.label :target_gender %><%= radio_button_tag(:target_gender, "Female") %><%= label_tag(:target_relationship, "Female") %><%= radio_button_tag(:target_gender, "Male") %><%= label_tag(:target_relationship, "Male") %><%= radio_button_tag(:target_gender, "Both", :checked => true) %><%= label_tag(:target_relationship, "Both") %>
  </div>
  <div class="calendar_details">
    <%= f.label :target_age_lower_limit %><%= f.select :target_age_lower_limit, (0..99) %>
  </div>
  <div class="calendar_details">
    <%= f.label :target_age_upper_limit %><%= f.select :target_age_upper_limit, (0..99) %>
  </div>
  <div class="calendar_details">
    <%= f.label :target_household_income_lower_limit %><%= f.select :target_household_income_lower_limit, ['Less than $10,000', '$10,000', '$20,000', '$30,000', '$40,000', '$50,000', '$60,000', '$70,000', '$80,000', '$90,000', '$100,000', '$110,000', '$120,000', '$130,000', '$140,000', '$150,000', '$160,000', '$170,000', '$180,000', '$190,000', '$190,000', '$200,000', 'More than $200,000'] %>
  </div>
  <div class="calendar_details">
    <%= f.label :target_household_income_upper_limit %><%= f.select :target_household_income_upper_limit, ['Less than $10,000', '$10,000', '$20,000', '$30,000', '$40,000', '$50,000', '$60,000', '$70,000', '$80,000', '$90,000', '$100,000', '$110,000', '$120,000', '$130,000', '$140,000', '$150,000', '$160,000', '$170,000', '$180,000', '$190,000', '$190,000', '$200,000', 'More than $200,000'] %>
  </div>

</div>

<div id="calendar_details_b2b">

  <div class="calendar_details">
    <%= f.label :target_company_size %><%= f.select :target_company_size, ['Self-employed', '1-10 employees', '11-50 employees', '51-200 employees', '201-500 employees', '501-1,000 employees', '1,001-5,000 employees', '5,001-10,000 employees', 'More than 10,000 employees'] %>
  </div>
  <div class="calendar_details">
    <%= f.label :target_industry %><%= f.select :target_industry, ['Art & Entertainment', 'Autos & Vehicles', 'Beauty & Fitness', 'Books & Litterature', 'Business & Industrial', 'Computer & Electronics', 'Finance', 'Food & Drinks', 'Games', 'Hobbies & Leisure', 'Home & Garden', 'Internet & Telecom', 'Jobs & Education', 'Law & Government', 'News', 'Online Communities', 'People & Society', 'Pets & Animals', 'Real Estate', 'Science', 'Shopping', 'Sports', 'Travel']  %>
  </div>

</div>

根据用户在第一个单选按钮(“B2C”或“B2B”)上检查的内容,我想显示 calendar_details_b2c divcalendar_details_b2b div

我知道我需要隐藏divs,然后实现某种形式的条件,检查哪个单选按钮被选中,最后显示右边的div

如您所见,我尝试向我的单选按钮添加一个onclick 选项和一些特定的类,但后来我卡住了:我不知道如何构建正确的 js 函数,而且我不知道知道在哪里包含它(在表单的.html.erb 文件中,在应用程序的标题中,在application.js 文件中?)。

————

更新:根据 Ziv Galili 的回答,这就是我现在所拥有的:

app/assets/javascript/custom/calendars.js:

$(document).ready(function() {
    $('input[type=radio][name=calendar').change(function () {
      // first: hide all the divs
      $('#calendar_details_b2c').css("display","none");
      $('#calendar_details_b2b').css("display","none");

      // then get the div ID to show (I stored it in the "value" of the radio button)
      var fieldToShow = $(this).val();
      // now use jQuery selector and change the display setting of that field
      $("#" + fieldToShow).css("display","block");
    });
});

application.js 中,我添加了//= require_tree ./custom 以便在我的应用中考虑上述代码。

在我的表单所在的视图(Calendars#New 视图)中,我现在有:

<div class="calendar_details">
    <%= f.label :target_relationship, "Business relationship" %>
    <%= f.radio_button :target_relationship, "calendar_details_b2c", :checked => true %>
    <%= f.label(:target_relationship, "B2C") %>
    <%= f.radio_button :target_relationship, "calendar_details_b2b", :checked => false %>
    <%= f.label(:target_relationship, "B2B") %>
  </div>

  <div class="calendar_details">
    <%= f.label :target_country, "Country" %><%= f.country_select :target_country, ["United States"] %>
  </div>

  <div id="calendar_details_b2c">

    <div class="calendar_details">
    <%= f.label :target_gender, "Gender" %><%= radio_button_tag(:target_gender, "Female") %><%= label_tag(:target_relationship, "Female") %><%= radio_button_tag(:target_gender, "Male") %><%= label_tag(:target_relationship, "Male") %><%= radio_button_tag(:target_gender, "Both", :checked => true) %><%= label_tag(:target_relationship, "Both") %>
    </div>
    <div class="calendar_details">
      <%= f.label :target_age_lower_limit, "Age / Lower limit" %><%= f.select :target_age_lower_limit, (0..99) %>
    </div>
    <div class="calendar_details">
      <%= f.label :target_age_upper_limit, "Age / Upper limit" %><%= f.select :target_age_upper_limit, (0..99) %>
    </div>
    <div class="calendar_details">
      <%= f.label :target_household_income_lower_limit, "Household income / Lower limit" %><%= f.select :target_household_income_lower_limit, ['Less than $10,000', '$10,000', '$20,000', '$30,000', '$40,000', '$50,000', '$60,000', '$70,000', '$80,000', '$90,000', '$100,000', '$110,000', '$120,000', '$130,000', '$140,000', '$150,000', '$160,000', '$170,000', '$180,000', '$190,000', '$190,000', '$200,000', 'More than $200,000'] %>
    </div>
    <div class="calendar_details">
      <%= f.label :target_household_income_upper_limit, "Household income / Upper limit" %><%= f.select :target_household_income_upper_limit, ['Less than $10,000', '$10,000', '$20,000', '$30,000', '$40,000', '$50,000', '$60,000', '$70,000', '$80,000', '$90,000', '$100,000', '$110,000', '$120,000', '$130,000', '$140,000', '$150,000', '$160,000', '$170,000', '$180,000', '$190,000', '$190,000', '$200,000', 'More than $200,000'] %>
    </div>

  </div>

  <div id="calendar_details_b2b">

    <div class="calendar_details">
      <%= f.label :target_company_size, "Company size" %><%= f.select :target_company_size, ['Self-employed', '1-10 employees', '11-50 employees', '51-200 employees', '201-500 employees', '501-1,000 employees', '1,001-5,000 employees', '5,001-10,000 employees', 'More than 10,000 employees'] %>
    </div>
    <div class="calendar_details">
      <%= f.label :target_industry, "Industry" %><%= f.select :target_industry, ['Art & Entertainment', 'Autos & Vehicles', 'Beauty & Fitness', 'Books & Litterature', 'Business & Industrial', 'Computer & Electronics', 'Finance', 'Food & Drinks', 'Games', 'Hobbies & Leisure', 'Home & Garden', 'Internet & Telecom', 'Jobs & Education', 'Law & Government', 'News', 'Online Communities', 'People & Society', 'Pets & Animals', 'Real Estate', 'Science', 'Shopping', 'Sports', 'Travel']  %>
    </div>

  </div>

但是,我似乎无法完成这项工作:当我访问 Calendars#New 视图时,我确实看到了选择 B2C 或 B2B 的单选按钮,但无论我选择哪个按钮,下面都没有显示任何内容( B2C 部分和 B2B 部分)。

我错过了什么?

————

UPDATE 2:所以,我将我的代码更新为 Ziv Galili 的新注释,即:注意按钮组的名称,实际上是calendar[target_relationship]

当我这样做并尝试转到我的视图时,我收到了 execJS::RuntimeError,这让我意识到我们使用的是纯 JavaScript,而我的 Rails 应用程序似乎使用的是 CoffeeScript。

所以,我删除了app/assets/javascript/custom/calendars.js,将 Ziv Galili 的代码转换为 CoffeeScript 并添加到 app/assets/javascript/calendars.coffee:

$('input[type=radio][name=calendar[target_relationship]]').change ->
  # first: hide all the divs
  $('#calendar_details_b2c').css 'display', 'none'
  $('#calendar_details_b2b').css 'display', 'none'
  # then get the div ID to show (i stored it in the "value" of the radio button
  fieldToShow = $(this).val()
  # now use jQuery selector and change the display setting of that field
  $('#' + fieldToShow).css 'display', 'block'
  return

我还将//= require_tree ./custom 替换为//= require_tree .,以确保我所有的.coffee 文件都是通过application.js 加载的。

尽管进行了所有这些代码更新,但我仍然没有得到我期望的结果:divs 都没有显示在我的视图中:

我一定遗漏了一些非常非常明显的东西,但我无法弄清楚它是什么。

有什么想法吗?

————

我们将不胜感激任何形式的帮助。

【问题讨论】:

    标签: javascript jquery ruby-on-rails forms ruby-on-rails-4


    【解决方案1】:

    我会这样做:

    jsFiddle

    解释:

    假设 HTML 将是:

    <form action="">
      <input type="radio" name="calendars" value="calendar_details_b2b">B2B
      <br>
      <input type="radio" name="calendars" value="calendar_details_b2c">B2C
    </form>
    <div id="calendar_details_b2c" style=>
      content of B2C
    </div>
    <div id="calendar_details_b2b">
      content of B2B
    </div>
    

    添加 css 代码,这样 div 不会在页面加载时显示:

    #calendar_details_b2c,
    #calendar_details_b2b
    {
      display: none;
    }
    

    JS 代码将是:

    $('input[type=radio][name=calendars]').change(function () {
      // first: hide all the divs
      $('#calendar_details_b2c').css("display","none");
      $('#calendar_details_b2b').css("display","none");
    
      // then get the div ID to show (i stored it in the "value" of the radio button
      var fieldToShow = $(this).val();
      // now use jQuery selector and change the display setting of that field
      $("#" + fieldToShow).css("display","block");
    });
    

    更新:

    至于您的更新,请注意在 JS 部分中按钮组的名称与它们在 HTML 文件中的名称匹配:

    js:

    $('input[type=radio][name=NAME_OF_BUTTON_GROUP]')
    

    要在 HTML 中查找名称,您可以(在 chrome 中):

    1. 右键单击其中一个单选按钮
    2. 按检查元素
    3. 在元素检查器中查找输入的名称属性

    &lt;input checked="checked" id="something_calendar_details_b2c" name="这就是名字" type="radio" value="calendar_details_b2c"&gt;

    注意:如果名称中有方括号(或任何其他特殊字符),则应使用撇号将其括起来

    $('input[type=radio][name="calendar[target_relationship]"]')
    

    【讨论】:

    • 非常感谢您的详细回答。一个简单的问题:我应该将 JS 代码放在 Rails 的什么位置?在我的 application.js 文件中?
    • 我在我的app/assets/javascript 文件夹中创建了一个custom.js 文件,然后我将//= require custom.js 添加到我的application.js 文件中以确保它包含在页面加载中。在custom.js 文件中,我粘贴了您的代码。但这似乎对我不起作用。知道我可能做错了什么吗?
    • JS 代码应该进入您所在控制器的相应 js 文件中(如果您在项目控制器中,则该文件应称为 projects.js)(这是我的意见,并不总是任何情况下的正确解决方案。)关于您的问题:尝试在 JS 文件中的代码周围添加环绕 $( document ).ready(function() { CODE });
    • 好的,非常感谢。我按照您的建议包装了我的 js 代码并将其移动到正确的文件中。您可以在 UPDATE 中看到我的问题已更新为所有相关代码。但是,似乎我仍然无法使其工作。知道我在做什么有什么问题吗?提前致谢!
    • 谢谢。我在 UPDATE 2 部分添加了一些新信息。我真的不明白我做错了什么......
    【解决方案2】:

    您可以在 js 文件中轻松使用 jQuery 函数。

    随便用

    $('input[type=radio][name=abc]').change(function() {
        // check radio button value by this.value
        // hide div blocks by $('div#id').hide();
    });
    

    【讨论】:

    • 谢谢,很有帮助。
    【解决方案3】:

    <script src="//code.jquery.com/jquery-1.11.1.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js"></script>
    <script>
    
    	$(function() {
              		var $divs = $('#divs > div');
              		$divs.first().show();
              		$('input[type=radio]').on('change',function() {
                    	$divs.hide();
                    	$divs.eq( $('input[type=radio]').index( this ) ).show();
               		});
    			});
    	
    </script>
      #divs div {
          display:none;
      }
    <div class="container">
    	<div class="form-container">
    		<form class="registerform" action="register.php" method="post" id="registerform">
    			<h3 class="title">Register</h3>
    			<div class="cdiv">User Name:</div>
    			<div class="cdiv"><input class="ipcontact" name="username" type="text" id="username"></div>
    			<div class="cdiv">Password:</div>
    			<div class="cdiv"><input class="ipcontact" name="password" type="password" id="password"></div>
    			<div class="cdiv">Name:</div>
    			<div class="cdiv"><input class="ipcontact" name="name" type="text" id="name"></div>
    			<div class="cdiv">E-mail:</div>
    			<div class="cdiv"><input class="ipcontact" name="email" type="email" id="email"></div>
    			<div class="cdiv">Phone Number:</div>
    			<div class="cdiv"><input class="ipcontact" name="phonenumber" type="number" id="phonenumber"></div>
    			<div class="cdiv">Student<input type="radio" name="check" checked value="1">Teacher<input type="radio" name="check" value="2"></div>
    
    
    			<div id = "divs">
    				<div class="form-group" id = "div2">
    					Student Class:<br/>
    					<input class="ipcontact" name="studentclass" type="text" id="studentclass"><br/>
    					Student Roll Number:<br/>
    					<input class="ipcontact" name="studentrollnumber" type="text" id="studentrollnumber"> 
    				</div>
    				<div class="form-group" id = "div1" >
    					Teacher type:<br/>
    					<input class="ipcontact" name="teachertype" type="text" id="teachertype">
    				</div>
    			</div>
    			<div class="form-group"> <input class="login-button" type="submit" name="submit" value="Register"></div>
    		</form>
    	</div>
    </div>
    <!DOCTYPE html>
    <html>
    
    <head>
    <script src="//code.jquery.com/jquery-1.11.1.js"></script>
    <script src="//ajax.aspnetcdn.com/ajax/jquery.validate/1.9/jquery.validate.min.js">                                    </script>
    </head>
    
    <body>
    <script>
    
    
    $(function() {
                var $divs = $('#divs > div');
                $divs.first().show();
                $('input[type=radio]').on('change',function() {
                    $divs.hide();
                    $divs.eq( $('input[type=radio]').index( this ) ).show();
                });
            });
    
    </script>
    
    <div class="container">
    <div class="form-container">
        <form class="registerform" action="register.php" method="post" id="registerform">
            <h3 class="title">Register</h3>
            <div class="cdiv">User Name:</div>
            <div class="cdiv"><input class="ipcontact" name="username" type="text" id="username"></div>
            <div class="cdiv">Password:</div>
            <div class="cdiv"><input class="ipcontact" name="password" type="password" id="password"></div>
            <div class="cdiv">Name:</div>
            <div class="cdiv"><input class="ipcontact" name="name" type="text" id="name"></div>
            <div class="cdiv">E-mail:</div>
            <div class="cdiv"><input class="ipcontact" name="email" type="email" id="email"></div>
            <div class="cdiv">Phone Number:</div>
            <div class="cdiv"><input class="ipcontact" name="phonenumber" type="number" id="phonenumber"></div>
            <div class="cdiv">Student<input type="radio" name="check" checked value="1">Teacher<input type="radio" name="check" value="2"></div>
    
    
            <div id = "divs">
                <div class="form-group" id = "div2">
                    Student Class:<br/>
                    <input class="ipcontact" name="studentclass" type="text" id="studentclass"><br/>
                    Student Roll Number:<br/>
                    <input class="ipcontact" name="studentrollnumber" type="text" id="studentrollnumber"> 
                </div>
                <div class="form-group" id = "div1" >
                    Teacher type:<br/>
                    <input class="ipcontact" name="teachertype" type="text" id="teachertype">
                </div>
            </div>
            <div class="form-group"> <input class="login-button" type="submit" name="submit" value="Register"></div>
        </form>
    </div>
    </div>
    
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 2016-03-06
      • 1970-01-01
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 2012-10-22
      • 1970-01-01
      • 2018-09-29
      • 1970-01-01
      相关资源
      最近更新 更多