简体   繁体   中英

Dynamically populate up to 3 dropdowns based on previous dropdown selections

I know similar questions have been asked but I have not found a solution.

I have a sample fiddle using some of my known years, months and days as a sample. Instead on manually adding select option divs for each year, I'd like the div id to dynamically populate based on the value of the year selected and so on.

I have all dropdown option values from my database (php, mysql, cakephp 1.3). The first dropdown contains unique years that reports have been entered. Once selected (onchange) perhaps, the second dropdown will only give unique Months that reports were entered for that selected year and then once the month is selected (onchange) a third dropdown will populate with the dates of each day a report was entered. Reports started in August of 2011 and have not been entered every month nor every day since.

Need help with my ajax to post selected option from first dropdown list to my controller, then get 2nd dropdown options from new query to db (model) based on the posted value. Let's assume user selects 2013 from the first dropdown, then ajax sends "2013" in a variable to my controller, the controller sends value to my Model and my Model queries the database to get distinct months within 2013 where reports where entered. And since the year is not over, the only months that should appear are January thru July. These populate my months dropdown and the user selects May in example. Ajax sends May or "05" to controller -> Model and the model queries DB to get unique days in May, 2013. This populates my third dropdown. I will have a hidden input field that will be all the selected values from the dropdowns in this format: MM/DD/YYYY. When user submits, this redirect user to the reports page for that date and shows all records entered on that day.

Thanks for helping...

    <select name="drop_1" id="drop_1">
        <option value="" selected="selected" disabled="disabled">Choose Year</option>
        <option value="">Select Year</option>
        <option value="2011">2011</option>
        <option value="2012">2012</option>
        <option value="2013">2013</option>
    </select>

    <select name="drop_2" id="drop_2">
        <option value="" selected="selected" disabled="disabled">Choose Month</option>
        <option value=""></option>
        <option value="01">January</option>
        <option value="02">February</option>
        <option value="03">March</option>
        <option value="04">April</option>
        <option value="05">May</option>
        <option value="06">June</option>
        <option value="07">July</option>
    </select>

     <select name="drop_3" id="drop_3">
        <option value="" selected="selected" disabled="disabled">Choose Day</option>
        <option value=""></option>
        <option value="05/11/2013">05/11/2013</option>
        <option value="05/12/2013">05/12/2013</option>
        <option value="05/13/2013">05/13/2013</option>
    </select>

-- this is my jQuery but it is not working...the $.get needs to get the value from my Model, index just iframes a new iteration of my page.

    $(document).ready(function() {
    $('#wait_1').hide();
    $('#drop_1').change(function(){
      $('#wait_1').show();
      $('#result_1').hide();
      $.get("index", {  
        func: "drop_1",
        drop_var: $('#drop_1').val()
      }, function(response){
        $('#result_1').fadeOut();
        setTimeout("finishAjax('result_1', '"+escape(response)+"')", 400);
      });
        return false;
    });
});

function finishAjax(id, response) {
  $('#wait_1').hide();
  $('#'+id).html(unescape(response));
  $('#'+id).fadeIn();
}
function finishAjax_tier_three(id, response) {
  $('#wait_2').hide();
  $('#'+id).html(unescape(response));
  $('#'+id).fadeIn();
}

-- here's my actual form excerpt from the view, "index" in cakephp 1.3

<div>
    <!-- Begin Date Selection -->
    <form name="udate" action="/reports/daily/" method="post">
    <?php
    echo "<select id='drop_1' name='drop_1' title='Use the drop list'>";
    echo '<option value="" disabled="disabled" selected="selected">'."Choose Year".'</option>';
        foreach ($years as $select_year) 
        {
        echo '<option value="', $select_year[0]["Year(dated)"], '">', $select_year[0]["Year(dated)"], '</option>';
        }
    echo "</select>";?>

    <?php
    echo "<select name='drop_2' id='drop_2' title='Use the drop list'>";
    echo '<option value="" disabled="disabled" selected="selected">'."Choose Month".'</option>';
        foreach ($months as $select_month) 
        {
        echo '<option value="', $select_month[0]["Month(dated)"], '">', $select_month[0]["Month(dated)"], '</option>';
        }
    echo "</select>";
    echo "<script type=\"text/javascript\">
    $('#wait_2').hide();
        $('#drop_2').change(function(){
          $('#wait_2').show();
          $('#result_2').hide();
          $.get(\"index\", {
            func: \"drop_2\",
            drop_var: $('#drop_2').val()
          }, function(response){
            $('#result_2').fadeOut();
            setTimeout(\"finishAjax_tier_three('result_2', '\"+escape(response)+\"')\", 400);
          });
            return false;
        });
    </script>";?>

    <?php
    echo "<select id='drop_3' name='drop_3' title='Use the drop list'>";
    echo '<option value="" disabled="disabled" selected="selected">'."Choose Day".'</option>';
        foreach ($days as $select_item) 
        {
        echo '<option value="', $select_item[0]["Days(dated)], '">', $select_item[0]["Days(dated)], '</option>';
        }
    echo "</select>";?>
  <span id="wait_1" style="display: none;">
    <img alt="Please Wait" src="http://dev.asi.calpoly.edu/img/ajax-loader.gif"/>
</span>
<span id="result_1" style="display: none;"></span>
<span id="wait_2" style="display: none;">
<img alt="Please Wait" src="http://dev.asi.calpoly.edu/img/ajax-loader.gif"/>
</span>
<span id="result_2" style="display: none;"></span> 
            <?php echo $form->submit('Submit') ?>
        </form>
    </div><!-- End Date Selection -->

What you should do is:

  1. Attach change events to each dropdown - or at least the first two.

  2. On a change event occuring make an AJAX call to the server (passing some params) and repopulate the next selectbox with what the server returns. The "trick" here is that you alone have to deside how to pass the parameters (GET, POST) and how to create the selectbox HTML.

  3. After the AJAX call completes and returns the data, you need to populate the next select. Here you can either have the server send ready HTML for the selects or get the data and build the markup client side. It should be better to have the HTML sent prerendered.

  4. Repeat the procedure for the next dropdown.

There's no need for multiple ajax calls. You can get all dates for the reports. And process the drop downs client side.

I'm not going to provide code. Its easy to codify, but you need to manipulate the data for you circumstance and that'll take some time.

Even Better Solution

  • Calendar instead of drop downs.

I will extend Borislav's answer a little, if I may, providing a concept to assist you.

The method Borislav describes is exactly right and IMHO is a good answer worthy of the bounty. I have used this with success BUT it is not intuitive for users and is not touchscreen friendly, which any new application really needs to be.

One pitfall to avoid: if you are going to use a form post (rather than reading the drops with JS) then you do need to include the empty s on page load or you will find they are very hard to get recognised. It is ok to replace them with others of the same name but reliably adding new form elements is a hassle you don't need.

<SELECT id='1st' name='1st' onChange='myajax(this.value)'><OPTIONS></SELECT><SPAN id='2span'><SELECT id='2nd' name='2nd' style='display: none;'>.... etc</SPAN>

works well, as does:

...Pick from Year first

your myajax function just replaces the 2span.innerHTML= whatever your php sent...

Might I suggest though, that you extend the solution to using a graphical UI instead. The simplest version of this would be buttons for year, month and date. HTML5 even has the ability to draw them for you dynamically. You can use your ajax to grey-out or hide any buttons that are not valid for a given year selection. It is as easy to return a load of code for buttons as a select statement after all. Just set onClick='myajax(\\"whatever\\")' when you generate the buttons.

I had a similar situation,I believe that you need to create Months and Days selects based on the values from the database, you can use php function date for example <option> echo date(d,Var) - let's assume that the var is the date from database was = 01/05/2013,in that case you the option will be '01',and in the case of month use <option> echo date(F,Var) in this case option is 'May' and so for the year.

Prepare a query to list all the report dates and then pick them from the query and populate them into your selects.

Check PHP date function .

This is the current JSFiddle

I have made alot of similar solutions. A very good ide is to save the dates that are choosen in variables. So when you change one of the fields, its corresponding variable is updated with its choosen value. On changing any of the selectboxes, all the other are updated via ajax separatly, with all the variables sent as hasch. This solves many problems with what is updated when in separate selects.

There is no problem if the user goes in the "correct" direction, problem occurs if he or she goes "back"... Above solves this.

<form name="myform">
    <div align="center">


<select name="optone" size="1"
onchange="functionOne(this[this.selectedIndex].value)">
    <option value=" " selected="selected"> </option>
    <option value="Parameter1Value1">Parameter1 First Choice</option>
    <option value="Parameter1Value2">Parameter1 Second Choice</option>
    <option value="Parameter1Value3">Parameter1 Third Choice</option>
</select>

<br><br>
<select name="opttwo" size="1" onchange="functionTwo(this[this.selectedIndex].value)">
    <option value=" " selected="selected"> </option>
    <option value="Parameter2Value1">Parameter2 First Choice</option>
    <option value="Parameter2Value2">Parameter2 Second Choice</option>
    <option value="Parameter2Value3">Parameter2 Third Choice</option>
</select>

<br><br>


<select name="optthree" size="1">
    <option value=" " selected="selected">Final Data for Third List</option>
</select><br><br>


</div></form>

<script>

var $DropDownOneSelected=null;
var $DropDownTwoSelected=null;


function functionOne($value1)
{
    $DropDownOneSelected=$value1;
    // Retrive Data for Second DropDown based on First DrowDown value

}
function functionTwo($value2)
{
    $DropDownTwoSelected=$value2;
    // Retrive Data for Third DropDown based on First and Second DrowDown value

}

</script>

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