简体   繁体   中英

Rails form - change select options based on another selected option through JavaScript

I am looking for a way to change the options in a rails form.select field through JavaScript based on the selected option for another select field.

The way I was trying to do this before was by using two separate fields with the same object and different sets of options, like so:

<%= form_with(model: my_model) do |form| %>

  <div class="form-floating" id="input">
    <%= form.select :input, ['a', 'b'], { }, class: "form-control" %>
    <%= form.label :input %>
  </div>

  <div class="form-floating" id="output1">
    <%= form.select :output, ['c', 'd'], { }, class: "form-control" %>
    <%= form.label :output %>
  </div>

  <div class="form-floating" id="output2">
    <%= form.select :output, ['e', 'f'], { }, class: "form-control" %>
    <%= form.label :output %>
  </div>

  <script>
    function onChange() {
      var selected = $('#input option:selected').text()
      if (selected == 'a') {
        $('#output1').show()
        $('#output2').hide()
      }
      if (selected == 'b') {
        $('#output1').hide()
        $('#output2').show()
      }
    }

    $('#input').change(onChange)
    $(window).on("turbolinks:load", onChange)
  </script>

  <%= form.submit class: "btn" %>
<% end %>

The problem with this method is that the :output field is created twice and only the last one (with id="output2") is submitted, so I'm now looking for a way to change the select options in the onChange() method for a single output form.select field.

Any help with this issue or an alternative solution would be greatly appreciated, cheers.

Short answer: Use $('#output-')prop('disabled', true); instead of .hide() .

Long answer:

According to the JQuery docs , .hide() doesn't actually disable the input, it just hides it with CSS. Same with .show() it looks like . So you need to be using a different method for this. More on that in a second.

Second, the reason that only the second select box is being sent through, output2 , is probably because they are both set up to be <%= form.select :output %> . According to the Rails docs , under the hood, Rails is setting both of these inputs up like this:

<select name="output"></select>

Since you have two select boxes with the same name attribute, they're overwriting each other. This is again because you're using .hide() and .show() , so they're not actually being disabled.

I think this would work in your scenario. Try using $("output").prop('disabled', true); like so:

  function onChange() {
      var selected = $('#input option:selected').text()
      if (selected == 'a') {
        $('#output1').show()
        $('#output2').prop('disabled', true);
      }
      if (selected == 'b') {
        $('#output1').prop('disabled', true);
        $('#output2').show()
      }
    }

If you're using JQuery Version < 1.5, you can use $("input").attr('disabled','disabled'); according to this Stack Overflow Answer .

Solved the problem, posting it here for anyone else having this problem. Basically I abandoned the rails form helper in favour of building up the html string using tags, something like this:

function replaceHTML() {
    var newHTML = '<select class="form-control" name="output" id="output">'

    var selection = $('#input option:selected').text()
    var options = selection == 'a' ? ['c', 'd'] : ['e', 'f']
    for (let i = 0; i < options.length; i++) {
      newHTML += '<option value=' + options[i] + '>' + options[i] + '</option>'
    }

    newHTML += '</select><label for="output">Output</label>'
    $('#output').html(newHTML)
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM