9

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 -->
sloga
  • 612
  • 2
  • 12
  • 31
  • should my url be the controller instead of view? – sloga Jul 08 '13 at 22:25
  • I'd avoid drop downs all together if you can. I've heard plenty of anti drop-down UX sentiments about this sort of thing. How about a calendar widget? – Parris Jul 09 '13 at 01:13
  • The drop downs are populated by years, months and days that reports were entered and reports were not entered in every year nor every month nor every day. I don't think a calendar widget would be a good solution. – sloga Jul 09 '13 at 15:09
  • Well if you just get dates for all reports you can highlight each day that a report was filled in the calendar. Users can skip back and forth through the months and years as they wish. Note: I'd just get the dates/ids/name not all report objects. If you really want to use drop downs you can do the same thing. I recommend pre-fetching all dates though. – Parris Jul 09 '13 at 18:43
  • Do you have some code samples of such a calendar widget that could gray out or diminish days that did not reports. Then I would need whatever day chosen to be submitted by the form so that it calls a new page with all the reports for that day. – sloga Jul 09 '13 at 22:25
  • Can't use calendar widget unless it is section 508 compliant. – sloga Jul 12 '13 at 15:23
  • I made a jQuery plugin for similar purposes some years ago, it might help you to grasp the idea https://github.com/AstDerek/AJAX-select-jQuery-plugin – Ast Derek Jul 13 '13 at 05:40
  • I still do not have a viable solution – sloga Aug 15 '13 at 17:51

6 Answers6

2

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.

Borislav Sabev
  • 4,776
  • 1
  • 24
  • 30
  • thanks. I am new to AJAX so it will be a bit of a struggle but I understand the concept. – sloga May 22 '13 at 22:55
  • On the server side (in Cake) "all you need to do" is to use the `ajax` layout in such actions. For example if you have the `exampleController` with it's `populateSelectTwo` action, in that action on the top you need to call `$this->layout = 'ajax';`. The `ajax` layout is just an empty layout. This is so, because when you do such ajax rendering you do not need to render the whole page as with regular calls - you only need to render the portion of HTML you're serving. I also suggest using [elements](http://book.cakephp.org/1.3/en/The-Manual/Developing-with-CakePHP/Views.html#elements) for these. – Borislav Sabev May 23 '13 at 06:56
  • Also please accept the answer if it helped. I can also provide deeper technical primers, but this concept seems enough for the seasoned. – Borislav Sabev May 23 '13 at 06:57
  • What I need assistance with is dynamically updating select dropdown lists using ajax based on a previously selected item. (the change events you mentioned) If you look at the jsfiddle I linked in my original post, you can see what I mean. I need the options to populate based on previous selection. – sloga Jun 04 '13 at 17:34
  • You've already attached the change events. Now make server side methods that return the data that you want to use in every next drop-down and call those methods via AJAX (`$.ajax()` function in jQuery) and populate the next selects. – Borislav Sabev Jun 05 '13 at 05:09
  • @BorislavSabev How to get as well as value automatic process by fills with all the drop down? – Gem Apr 02 '19 at 07:13
  • in my case the change event on 3rd dropdown is not firing on the 2nd drowdown population. – user1451111 May 28 '19 at 02:48
0

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.
Community
  • 1
  • 1
Parris
  • 17,833
  • 17
  • 90
  • 133
  • Thanks but the datepicker does not meet our accessibility requirements. https://www.ssbbartgroup.com/blog/2013/07/03/jquery-ui-accessibility-analysis/ – sloga Jul 12 '13 at 15:24
  • @sloga the 2nd calendar I mentioned isn't jQueryUI based and doesn't require an input field; however, I understand that you wouldn't be able to get approval for it, for whatever reason :). Requesting all dates is still the better experience though. – Parris Jul 12 '13 at 17:49
  • I need to learn how to write ajax so when user chooses a year it sends that value back to the DB to query months from that year that records were entered. Then upon that select (choosing a month) I need ajax to send that value to query the DB to get which days were entered in the reports. I don't know how to write the ajax. – sloga Jul 12 '13 at 23:33
  • @Parris My code : https://justpaste.it/41qcp, if i select one and one then how to get custom value like $10. – Gem Apr 02 '19 at 07:18
0

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.

Robert Seddon-Smith
  • 987
  • 1
  • 9
  • 13
0

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

Ahmed Ali
  • 977
  • 1
  • 12
  • 25
  • How would I submit what the user selects in year back to the database to query the months (not all months have reports). I know how to write the SQL but I don't know how to have ajax get the value onChange and send it to the DB. – sloga Jul 12 '13 at 23:07
  • have you considered using `` – Ahmed Ali Jul 12 '13 at 23:15
  • I do not understand your comment. In the JSFiddle, the html is static but in actuality the month and days selects will be dynamically populated based on what the user selects so I was thinking ajax would be best to send what the user selects back to query my database table. I do not know how to get the value into a variable and write the ajax. – sloga Jul 12 '13 at 23:37
  • i understood your point,that needs some logic to be set first,but why don't you allow user to input any date,and then if the data exist then display the report for that date,else display a message stating that,no info available. – Ahmed Ali Jul 13 '13 at 00:06
  • I'm getting closer but my function dates() is not working. Trying to get all the values and concatenate into the input text field which I will hide and use it to submit. should be a date like: 07/12/2013. see JSFiddle - http://jsfiddle.net/sloga/KdskX/17/ – sloga Jul 13 '13 at 00:13
  • i managed to fix the issue for you, check [this](http://jsfiddle.net/ahmedadil1000/KdskX/20/) ,now month are coming with names,you can change that to pick the value of selected month. – Ahmed Ali Jul 13 '13 at 00:44
  • not working for me, try jsfiddle.net/sloga/KdskX/22 - I wonder if the script is running before. – sloga Jul 13 '13 at 02:53
  • this is working but I still need to figure out the ajax get/post to from db - http://jsfiddle.net/sloga/KdskX/23/ – sloga Jul 13 '13 at 03:28
  • check [this](http://stackoverflow.com/questions/5568965/get-data-from-mysql-database-to-use-in-javascript) and if you need help just let me know – Ahmed Ali Jul 13 '13 at 06:26
  • you check the last link i sent? – Ahmed Ali Jul 16 '13 at 22:57
0

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.

Björn3
  • 297
  • 1
  • 2
  • 8
0
<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>
Hardik Sondagar
  • 4,347
  • 3
  • 28
  • 48