Rails 4 - dynamically populate 2nd select menu based on choice in first select menu in a nested form
<p>I have models for Project and Ethic in my Rails 4 app.</p>

<p>The ethics view has a nested fields form (using simple form simple fields for) contained in it. The ethic form fields are nested in the projects form.</p>

<p>The ethic form fields has 2 select menus.  The first menu offers a set of options for a category. The 2nd select option is a list of subcategories. </p>

<p>I'm trying to figure out how to populate the 2nd select menu with the right options, based on the choice made in the 1st select menu.</p>

<p>In my project.js file, I have:</p>

<pre><code>jQuery(document).ready(function() {

   jQuery("#project_ethic_attributes.main_category").change(function() {
      var category = $("#project_ethic_attributes.main_category").val(),
        sub_category = $("#project_ethic_attributes.sub_category"),
        options = [],
        str = "";
      sub_category.find('option').remove();
      if(category == 'Risk of harm'){
      options = ["Physical Harm", "Psychological distress or discomfort", "Social disadvantage", "Harm to participants", "Financial status", "Privacy"]
    }

   });

   // jQuery(".main_category").change(function() {
   //  var category = $(".main_category").val(),
   //      sub_category = $(".sub_category"),
   //      options = [],
   //      str = "";
   //  sub_category.find('option').remove();

   //  if(category == 'Risk of harm'){
   //    options = ["Physical Harm", "Psychological distress or discomfort", "Social disadvantage", "Harm to participants", "Financial status", "Privacy"]
   //  }
   //  else if(category == 'Informed consent'){
   //    options = ["Explanation of research", "Explanation of participant's role in research"]   
   //  }
   //  else if(category == 'Anonymity and Confidentiality'){
   //    options = ["Remove identifiers", "Use proxies", "Disclosure for limited purposes"]
   //  }
   //  else if(category == 'Deceptive practices'){
   //    options = ["Feasibility"]
   //  }
   //  else if(category == 'Right to withdraw'){
   //    options = ["Right to withdraw from participation in the project"]  
   //  }
   //  if(options.length &gt; 0){
   //    for(i=0;i&lt;options.length;i++){
   //      str = '&lt;option value="' + options[i] + '"&gt;' + options[i] + '&lt;/option&gt;'
   //      sub_category.append(str);
   //    }
   //    sub_category.val(options[0]);
   //  }


});
</code></pre>

<p>I can't figure out what Im doing wrong. Regardless of the choice I make in the 1st option, the 2nd select menu is populated with options that belong to the last category.</p>

<p>My projects form has:</p>

<pre><code> &lt;%= f.simple_fields_for :ethics do |f| %&gt;
        &lt;%= render 'ethics/ethic_fields', f: f %&gt;
 &lt;% end %&gt;
 &lt;%= link_to_add_association 'Add an ethics consideration', f, :ethics, partial: 'ethics/ethic_fields' %&gt;
</code></pre>

<p>My ethic form fields has:</p>

<pre><code>&lt;%= f.input :category, collection: [ "Risk of harm", "Informed consent", "Anonymity and Confidentiality", "Deceptive practices", "Right to withdraw"], :label =&gt; "Principle",  prompt: 'select', id: "main_category" %&gt;


            &lt;%= f.input :subcategory,  collection: text_for_subcategory(@category), :label =&gt; "Subcategory", prompt: 'select', id: "sub_category" %&gt;
</code></pre>

<p>My ethic view helper has:</p>

<pre><code>def text_for_subcategory(category)
      if category == 'Risk of harm'
            [ "Physical Harm", "Psychological distress or discomfort", "Social disadvantage", "Harm to participants", "Financial status", "Privacy"]
        elsif category == 'Informed consent'
            ["Explanation of research", "Explanation of participant's role in research"]
        elsif category == 'Anonymity and Confidentiality'
            ["Remove identifiers", "Use proxies", "Disclosure for limited purposes"]
        elsif category == 'Deceptive practices' 
            ["Feasibility"] 
        else category == 'Right to withdraw'    
            ["Right to withdraw from participation in the project"] 
       end
    end  
</code></pre>

<p>Can anyone see what i need to do to populate the second select menu with the right options based on the choice made in the 1st select menu. I'm wondering if I'm not supposed to write the jQuery in the project.js file, given the form fields are contained within an ethic view partial (rendered in the projects form).</p>

<p><strong>MIXAN'S SUGGESTION</strong></p>

<p>My form now has:</p>

<pre><code>&lt;%= f.input :category, collection: [ "Risk of harm", "Informed consent", "Anonymity and Confidentiality", "Deceptive practices", "Right to withdraw"], option:'disabled selected value', :label =&gt; "Principle",  prompt: 'select', id: "main_category" %&gt;


        &lt;%= f.input :subcategory,  :label =&gt; "Subcategory", prompt: 'select', id: "sub_category", option:'disabled' %&gt;
</code></pre>

<p>I had to change the form a bit because I use simple form with rails. I'm not sure if I have added the 'disabled selected value' and 'disabled' options to the form inputs correctly. </p>

<p>At the moment, the form renders- but the second menu is not populated with any content. I wonder if that has something to do with the use of the option tags in the js file?</p>

<p>ethics.js has:</p>

<pre><code>jQuery(document).ready(function() {
  var optionsMap = {
      'Risk of harm': [
        'Physical Harm', 
        'Psychological distress or discomfort', 
        'Social disadvantage', 
        'Harm to participants', 
        'Financial status', 
        'Privacy'
      ],
      'Informed consent': [
        'Explanation of research', 
        "Explanation of participant's role in research"
      ],
      'Anonymity and Confidentiality': [
        'Remove identifiers', 'Use proxies', 'Disclosure for limited purposes'
      ],
      'Deceptive practices': [
        'Feasibility'
      ],
      'Right to withdraw': [
        'Right to withdraw from participation in the project'
      ]
    };

  jQuery('#main_category').change(function() {
    var category = jQuery(this).val(),
        $subCategory = jQuery('#sub_category'),
        newOptions = optionsMap[category];
    $subCategory.attr('disabled', false)
    $subCategory.empty();
    $.each(newOptions, function() {
      $subCategory.append(jQuery("&lt;option&gt;&lt;/option&gt;").text(this));
    });
  })
});
</code></pre>

<p><strong>MIXAN'S AMENDED SUGGESTION</strong></p>

<pre><code>&lt;%= f.select :category, collection: [ "Risk of harm", "Informed consent", "Anonymity and Confidentiality", "Deceptive practices", "Right to withdraw"], option:'disabled selected value', :label =&gt; "Principle", prompt: 'select', html: { id: "main_category" } %&gt;


&lt;%= f.select :subcategory, [], {}, id: "sub_category", disabled: true %&gt;
</code></pre>

<p>When I try this, the formatting of the menu drop down for the first category is changed, but the functionality is the same as when I use f.input. The second menu does not populate with any options though.</p>