40

I have two selects:

<select name="select1" id="select1">
    <option value="1">Fruit</option>
    <option value="2">Animal</option>
    <option value="3">Bird</option>
    <option value="4">Car</option>
</select>

<select name="select2" id="select2">
    <option value="1">Banana</option>
    <option value="1">Apple</option>
    <option value="1">Orange</option>
    <option value="2">Wolf</option>
    <option value="2">Fox</option>
    <option value="2">Bear</option>
    <option value="3">Eagle</option>
    <option value="3">Hawk</option>
    <option value="4">BWM<option>
</select>

How do I do that with jQuery if I choose Fruit in the first select? The second select would show me only Fruits - Banana, Apple, Orange. If I choose Bird in the first select, the second select would show me only Birds - Eagle, Hawk. And so on...

I tried to do it with this piece of jQuery code:

$("#select1").change(function() {
    var id = $(this).val();
    $('#select2 option[value!='+id+']').remove();
});

Unfortunately, it removes almost everything, and I have no idea how to bring back some options. I also read something about clone, but I don't know how to use it in this case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Randy
  • 451
  • 1
  • 4
  • 8
  • http://stackoverflow.com/questions/10200498/jquery-conditional-show-an-element-based-on-drop-down-box-selection this may help your problem – sujal May 13 '12 at 10:19
  • @santo, unfortunately hide only works with Firefox. – Randy May 13 '12 at 10:26
  • @Randy Looking at this again I do have one question; when you submit the form, how will you pass the selected value of `select2`? The values are not unique, so what separates Banana from Apple? – Ja͢ck May 13 '12 at 11:19
  • @Jack, it's just an example. I also add unique name to all select options. – Randy May 13 '12 at 11:28
  • @Randy Okay that's your prerogative, it's just additional work when you submit the form :) – Ja͢ck May 13 '12 at 11:33

8 Answers8

75

$("#select1").change(function() {
  if ($(this).data('options') === undefined) {
    /*Taking an array of all options-2 and kind of embedding it on the select1*/
    $(this).data('options', $('#select2 option').clone());
  }
  var id = $(this).val();
  var options = $(this).data('options').filter('[value=' + id + ']');
  $('#select2').html(options);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<select name="select1" id="select1">
  <option value="1">Fruit</option>
  <option value="2">Animal</option>
  <option value="3">Bird</option>
  <option value="4">Car</option>
</select>


<select name="select2" id="select2">
  <option value="1">Banana</option>
  <option value="1">Apple</option>
  <option value="1">Orange</option>
  <option value="2">Wolf</option>
  <option value="2">Fox</option>
  <option value="2">Bear</option>
  <option value="3">Eagle</option>
  <option value="3">Hawk</option>
  <option value="4">BWM<option>
</select>

Using jQuery data() to store data

I guess hiding elements doesn't work cross-browser(2012), I have'nt tested it myself.

long
  • 3,692
  • 1
  • 22
  • 38
sabithpocker
  • 15,274
  • 1
  • 42
  • 75
  • Great solution. I wasn't aware of `.hide()` not working x-browser – billyonecan May 13 '12 at 11:01
  • 1
    @sabithpocker, of course I marked it. One small question. What I should add to this code that when page is just loaded or refreshed the second select already would show me only the Fruits options - Banana, Apple, Orange; not all options. – Randy May 13 '12 at 11:20
  • 2
    @Randy $("#select1").trigger('change'); This way you can explicitly invoke change event. or just $('#select1').change(); will do the same. – sabithpocker May 13 '12 at 11:38
  • @sabithpocker, wow it works flawlessly now with all browsers, even IE. Thank you so much! – Randy May 13 '12 at 11:46
  • The problem with this is that, if this is in a form, you can't tell which #select2 option was chosen since they all have the same value. In HTML5, i used – Gadi Jan 15 '16 at 05:09
  • @Gadi Please feel free to add your solution. This one was made to tackle an issue with cross-browser implementation of such a scenario. – sabithpocker Jan 15 '16 at 14:39
  • 3
    The answer above is great, and I didn't change it much. I only noticed that, if I use it in a form, I can't distinguish between "Banana", "Apple", "Orange", since they all have the same value (1). Adding "data-value" fixed this. – Gadi Jan 25 '16 at 01:23
  • What is the best way to edit it to also not remove optgroup values? – Andreas Mattisson Mar 07 '17 at 13:29
  • Great solution. FYI - I had to enclose this in $(function(ready){ ... }); to get a stand alone test working. – FeralReason Nov 02 '19 at 18:13
  • What will be the code if I want second list will show at once in a list but not hidden? – Hadisur Rahman May 19 '20 at 09:33
  • what if i need to add the third select options, and it getting populated by the first. I've tried it, but I always get the duplicate value from the second select options. Please, I need your help – Mauliardiwinoto Jul 05 '20 at 02:17
  • 1
    @Mauliardiwinoto You will have to store the third select option also with `$(this).data('optionsForThird'...` and then filter it. Please explain your scenario clearly as in how the 3 selects are related to each other with an example. You can post a question and then add a link here as comment. – sabithpocker Jul 05 '20 at 13:17
  • I've got my answer ... Thanks :) https://stackoverflow.com/questions/62736578/populated-select-with-html-js – Mauliardiwinoto Jul 10 '20 at 13:25
11

I wanted to make a version of this that uses $.getJSON() from a separate JSON file.

Demo: here

JavaScript:

$(document).ready(function () {
    "use strict";

    var selectData, $states;

    function updateSelects() {
        var cities = $.map(selectData[this.value], function (city) {
            return $("<option />").text(city);
        });
        $("#city_names").empty().append(cities);
    }

    $.getJSON("updateSelect.json", function (data) {
        var state;
        selectData = data;
        $states = $("#us_states").on("change", updateSelects);
        for (state in selectData) {
            $("<option />").text(state).appendTo($states);
        }
        $states.change();
    });
});

HTML:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body>
    <select id="us_states"></select>
    <select id="city_names"></select>
    <script type="text/javascript" src="updateSelect.js"></script>
</body>
</html>

JSON:

{
    "NE": [
        "Smallville",
        "Bigville"
    ],
    "CA": [
        "Sunnyvale",
        "Druryburg",
        "Vickslake"
    ],
    "MI": [
        "Lakeside",
        "Fireside",
        "Chatsville"
    ]
}
Xitalogy
  • 1,592
  • 1
  • 14
  • 17
9

Store all #select2's options in a variable, filter them according to the value of the chosen option in #select1, and set them using .html() in #select2:

var $select1 = $( '#select1' ),
    $select2 = $( '#select2' ),
    $options = $select2.find( 'option' );

$select1.on('change', function() {
    $select2.html($options.filter('[value="' + this.value + '"]'));
}).trigger('change'); 

Here's a fiddle

billyonecan
  • 20,090
  • 8
  • 42
  • 64
  • @billyonecan. Thanks for your code it's look simple to understand, but if i have more two selected options how to show based on first two selected options can you explain it in fiddle. – jvk Jan 21 '17 at 18:52
2

I built on sabithpocker's idea and made a more generalized version that lets you control more than one selectbox from a given trigger.

I assigned the selectboxes I wanted to be controlled the classname "switchable," and cloned them all like this:

$j(this).data('options',$j('select.switchable option').clone());

and used a specific naming convention for the switchable selects, which could also translate into classes. In my case, "category" and "issuer" were the select names, and "category_2" and "issuer_1" the class names.

Then I ran an $.each on the select.switchable groups, after making a copy of $(this) for use inside the function:

var that = this;
$j("select.switchable").each(function() { 
    var thisname = $j(this).attr('name');
    var theseoptions = $j(that).data('options').filter( '.' + thisname + '_' + id );
    $j(this).html(theseoptions);
});     

By using a classname on the ones you want to control, the function will safely ignore other selects elsewhere on the page (such as the last one in the example on Fiddle).

Here's a Fiddle with the complete code:

Tom McGee
  • 76
  • 7
1

All of these methods are great. I have found another simple resource that is a great example of creating a dynamic form using "onchange" with AJAX.

http://www.w3schools.com/php/php_ajax_database.asp

I simply modified the text table output to anther select dropdown populated based on the selection of the first drop down. For my application a user will select a state then the second dropdown will be populated with the cities for the selected state. Much like the JSON example above but with php and mysql.

1

I have found the solution as followiing... working for me perfectly :)

$(document).ready(function(){
$("#selectbox1").change(function() {
    var id = $(this).val();
    $("#selectbox2").val(id);
 });   });
Moiz Ahmad
  • 144
  • 10
0

Try to use it:

Drop-down box dependent on the option selected in another drop-down box. Use jQuery to change a second select list based on the first select list option.

<asp:HiddenField ID="hdfServiceId" ClientIDMode="Static" runat="server" Value="0" />
<asp:TextBox ID="txtOfferId" CssClass="hidden" ClientIDMode="Static" runat="server" Text="0" />
<asp:HiddenField ID="SelectedhdfServiceId" ClientIDMode="Static" runat="server" Value="0" />
<asp:HiddenField ID="SelectedhdfOfferId" ClientIDMode="Static" runat="server" Value="0" />

<div class="col-lg-2 col-md-2 col-sm-12">
    <span>Service</span>
    <asp:DropDownList ID="ddlService" ClientIDMode="Static" runat="server" CssClass="form-control">
    </asp:DropDownList>
</div>
<div class="col-lg-2 col-md-2 col-sm-12">
    <span>Offer</span>
    <asp:DropDownList ID="ddlOffer" ClientIDMode="Static" runat="server" CssClass="form-control">
    </asp:DropDownList>
</div>

Use jQuery library in your web page.

<script type="text/javascript">
    $(document).ready(function () {
        ucBindOfferByService();
        $("#ddlOffer").val($('#txtOfferId').val());
    });

    $('#ddlOffer').on('change', function () {
        $("#txtOfferId").val($('#ddlOffer').val());
    });

    $('#ddlService').on('change', function () {
        $("#SelectedhdfOfferId").val("0");
        SetServiceIds();
        var SelectedServiceId = $('#ddlService').val();
        $("#SelectedhdfServiceId").val(SelectedServiceId);
        if (SelectedServiceId == '0') {
        }
        ucBindOfferByService();
        SetOfferIds();
    });

    function ucBindOfferByService() {
        GetVendorOffer();
        var SelectedServiceId = $('#ddlService').val();
        if (SelectedServiceId == '0') {
            $("#ddlOffer").empty();
            $("#ddlOffer").append($("<option></option>").val("0").html("All"));
        }
        else {
            $("#ddlOffer").empty();
            $(document.ucVendorServiceList).each(function () {
                if ($("#ddlOffer").html().length == "0") {
                    $("#ddlOffer").append($("<option></option>").val("0").html("All"));
                }
                $("#ddlOffer").append($("<option></option>").val(this.OfferId).html(this.OfferName));
            });
        }
    }

    function GetVendorOffer() {
        var param = JSON.stringify({ UserId: $('#hdfUserId').val(), ServiceId: $('#ddlService').val() });
        AjaxCall("DemoPage.aspx", "GetOfferList", param, OnGetOfferList, AjaxCallError);
    }

    function OnGetOfferList(response) {
        if (response.d.length > 0)
            document.ucVendorServiceList = JSON.parse(response.d);
    }

    function SetServiceIds() {
        var SelectedServiceId = $('#ddlService').val();
        var ServiceIdCSV = ',';
        if (SelectedServiceId == '0') {
            $('#ddlService > option').each(function () {

                ServiceIdCSV += $(this).val() + ',';
            });
        }
        else {
            ServiceIdCSV += SelectedServiceId + ',';
        }
        $("#hdfServiceId").val(ServiceIdCSV);
    }

    function SetOfferIds() {
        var SelectedServiceId = $('#ddlService').val();
        var OfferIdCSV = ',';
        if (SelectedServiceId == '0') {
            $(document.ucVendorServiceList).each(function () {
                OfferIdCSV += this.OfferId + ',';
            });
        }
        else {
            var SelectedOfferId = $('#ddlOffer').val();
            if (SelectedOfferId == "0") {
                $('#ddlOffer > option').each(function () {
                    OfferIdCSV += $(this).val() + ',';
                });
            }
            else {
                OfferIdCSV += SelectedOfferId + ',';
            }
        }
    }
</script>

Use Backend code in your web page.

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        ServiceList();
    }
}

public void ServiceList()
{
    ManageReport manageReport = new ManageReport();
    DataTable ServiceList = new DataTable();
    ServiceList = manageReport.GetServiceList();
    ddlService.DataSource = ServiceList;
    ddlService.DataTextField = "serviceName";
    ddlService.DataValueField = "serviceId";
    ddlService.DataBind();
    ddlService.Items.Insert(0, new ListItem("All", "0"));
}

public DataTable GetServiceList()
{
    SqlParameter[] PM = new SqlParameter[]
    {
        new SqlParameter("@Mode"    ,"Mode_Name"    ),
        new SqlParameter("@UserID"  ,UserId         )
    };
    return SqlHelper.ExecuteDataset(new SqlConnection(SqlHelper.GetConnectionString()), CommandType.StoredProcedure, "Sp_Name", PM).Tables[0];
}

[WebMethod]
public static String GetOfferList(int UserId, String ServiceId)
{
    var sOfferList = "";
    try
    {
        CommonUtility utility = new CommonUtility();
        ManageReport manageReport = new ManageReport();
        manageReport.UserId = UserId;
        manageReport.ServiceId = ServiceId;
        DataSet dsOfferList = manageReport.GetOfferList();
        if (utility.ValidateDataSet(dsOfferList))
        {
            //DataRow dr = dsEmployerUserDepartment.Tables[0].NewRow();
            //dr[0] = "0";
            // dr[1] = "All";
            //dsEmployerUserDepartment.Tables[0].Rows.InsertAt(dr, 0);
            sOfferList = utility.ConvertToJSON(dsOfferList.Tables[0]);
        }
        return sOfferList;
    }
    catch (Exception ex)
    {
        return "Error Message: " + ex.Message;
    }
}

public DataSet GetOfferList()
{
    SqlParameter[] sqlParameter = new SqlParameter[]
        {                                                                     
            new SqlParameter("@Mode"        ,"Mode_Name"    ),
            new SqlParameter("@UserID"      ,UserId         ),
            new SqlParameter("@ServiceId"   ,ServiceId      )
        };
    return SqlHelper.ExecuteDataset(new SqlConnection(SqlHelper.GetConnectionString()), CommandType.StoredProcedure, "Sp_Name", sqlParameter);
}
Fezal halai
  • 756
  • 7
  • 14
0

On the selected answer I see that when initially the page is loaded the selection of first option is prior fixed and therefore gives the option of all the categories in selection 2. You can avoid that by adding the first option as the following in both the select tag:- <option value="none" selected disabled hidden>Select an Option</option>

<select name="select1" id="select1">
<option value="none" selected disabled hidden>Select an Option</option>
<option value="1">Fruit</option>
  <option value="2">Animal</option>
  <option value="3">Bird</option>
  <option value="4">Car</option>
</select>


<select name="select2" id="select2">
<option value="none" selected disabled hidden>Select an Option</option>
  <option value="1">Banana</option>
  <option value="1">Apple</option>
  <option value="1">Orange</option>
  <option value="2">Wolf</option>
  <option value="2">Fox</option>
  <option value="2">Bear</option>
  <option value="3">Eagle</option>
  <option value="3">Hawk</option>
  <option value="4">BWM<option>
</select>