根据之前的下拉选择动态填充多达 3 个下拉列表

Posted

技术标签:

【中文标题】根据之前的下拉选择动态填充多达 3 个下拉列表【英文标题】:Dynamically populate up to 3 dropdowns based on previous dropdown selections 【发布时间】:2013-05-16 18:43:37 【问题描述】:

我知道有人问过类似的问题,但我没有找到解决方案。

我有一个sample fiddle,使用我已知的一些年、月和日作为样本。而不是手动添加每年的选择选项 div,我希望 div id 根据所选年份的值动态填充,依此类推。

我的数据库中有所有下拉选项值(phpmysql、cakephp 1.3)。第一个下拉列表包含已输入报告的唯一年份。一旦选择(onchange),第二个下拉列表将仅给出为该选定年份输入报告的唯一月份,然后一旦选择了月份(onchange),第三个下拉列表将填充输入报告的每一天的日期。报告于 2011 年 8 月开始,此后每月或每天都没有输入。

在我的 ajax 方面需要帮助将所选选项从第一个下拉列表发布到我的控制器,然后根据发布的值从新查询中获取第二个下拉选项到 db(模型)。假设用户从第一个下拉列表中选择 2013,然后 ajax 将变量中的“2013”​​发送到我的控制器,控制器将值发送到我的模型,我的模型查询数据库以获取 2013 年输入报告的不同月份。由于这一年还没有结束,应该出现的唯一月份是 1 月到 7 月。这些填充了我的月份下拉列表,并且用户在示例中选择了 May。 Ajax 将 May 或“05”发送到控制器 -> 模型,模型查询数据库以获得 2013 年 5 月的唯一日期。这填充了我的第三个下拉列表。我将有一个隐藏的输入字段,它将是下拉列表中的所有选定值,格式为:MM/DD/YYYY。当用户提交时,这会将用户重定向到该日期的报告页面并显示当天输入的所有记录。

感谢您的帮助...

    <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>

-- 这是我的 jQuery,但它不工作...... $.get 需要从我的模型中获取值,索引只是 iframes 我页面的新迭代。

    $(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();

-- 这是我从视图中摘录的实际表单,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  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  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 -->

【问题讨论】:

我的 url 应该是控制器而不是视图吗? 如果可以的话,我会尽量避免下拉。我听说过很多关于这类事情的反下拉用户体验情绪。日历小部件怎么样? 下拉列表由输入报告的年、月和天填充,并且每年、每个月或每天都没有输入报告。我认为日历小部件不是一个好的解决方案。 如果您只是获取所有报告的日期,您可以在日历中突出显示报告填写的每一天。用户可以根据需要来回跳过月份和年份。注意:我只是获取日期/ID/名称而不是所有报告对象。如果你真的想使用下拉菜单,你可以做同样的事情。我建议预取所有日期。 您是否有一些此类日历小部件的代码示例,这些示例可能会使未报告的日期变灰或减少。然后我需要表单选择提交的任何日期,以便它调用一个包含当天所有报告的新页面。 【参考方案1】:

你应该做的是:

    将更改事件附加到每个下拉菜单 - 或至少前两个。

    在发生更改事件时,对服务器进行 AJAX 调用(传递一些参数)并使用服务器返回的内容重新填充下一个选择框。这里的“诀窍”是您必须独自决定如何传递参数(GET、POST)以及如何创建选择框 HTML。

    AJAX 调用完成并返回数据后,您需要填充下一个选择。在这里,您可以让服务器为选择发送准备好的 HTML,或者获取数据并构建标记客户端。最好预先渲染发送的 HTML。

    对下一个下拉菜单重复该过程。

【讨论】:

谢谢。我是 AJAX 新手,所以会有点困难,但我理解这个概念。 在服务器端(在 Cake 中)“所有你需要做的”就是在这些操作中使用 ajax 布局。例如,如果您有带有populateSelectTwo 操作的exampleController,则在顶部的该操作中您需要调用$this-&gt;layout = 'ajax';ajax 布局只是一个空布局。之所以如此,是因为当您执行此类 ajax 渲染时,您不需要像常规调用那样渲染整个页面 - 您只需要渲染您正在服务的 HTML 部分。我还建议对这些使用elements。 如果有帮助,也请接受答案。我还可以提供更深入的技术入门,但这个概念对于经验丰富的人来说似乎已经足够了。 我需要帮助的是根据先前选择的项目使用 ajax 动态更新选择下拉列表。 (您提到的更改事件)如果您查看我在原始帖子中链接的 jsfiddle,您就会明白我的意思。我需要根据之前的选择来填充选项。 您已经附加了更改事件。现在让服务器端方法返回您想要在每个下一个下拉列表中使用的数据,并通过 AJAX(jQuery 中的$.ajax() 函数)调用这些方法并填充下一个选择。【参考方案2】:

不需要多个 ajax 调用。您可以获得报告的所有日期。并在客户端处理下拉菜单。

我不会提供代码。它易于编码,但您需要根据具体情况处理数据,这需要一些时间。

更好的解决方案

日历而不是下拉菜单。 如果你想使用 jQueryUIs 日历小部件,这篇文章会很有用:Highlight dates in specific range with jQuery's datepicker。简而言之,您使用 beforeShowDay 选项并传入它是否可选择、要使用的 css 类和要显示的工具提示文本。 否则,我在几年前使用过这个小部件,当时发现它很有用:http://arshaw.com/fullcalendar/。它看起来很像谷歌日历。

【讨论】:

谢谢,但日期选择器不符合我们的可访问性要求。 ssbbartgroup.com/blog/2013/07/03/… @sloga 我提到的第二个日历不是基于 jQueryUI 的,不需要输入字段;但是,我知道无论出于何种原因,您都无法获得批准:)。不过,请求所有日期仍然是更好的体验。 我需要学习如何编写 ajax,因此当用户选择一年时,它会将该值发送回数据库以查询输入记录的那一年的月份。然后在选择时(选择一个月),我需要 ajax 发送该值以查询数据库以获取在报告中输入的日期。我不知道怎么写ajax。 @Parris 我的代码:justpaste.it/41qcp,如果我选择一个和一个,那么如何获得像 $10 这样的自定义值。【参考方案3】:

如果可以的话,我会稍微扩展鲍里斯拉夫的回答,提供一个概念来帮助你。

鲍里斯拉夫描述的方法完全正确,恕我直言,这是一个值得赏金的好答案。我已经成功地使用了它,但它对用户来说并不直观,并且对触摸屏不友好,这是任何新应用程序都真正需要的。

要避免的一个陷阱:如果您要使用表单帖子(而不是使用 JS 阅读 drop),那么您确实需要在页面加载时包含空的 s,否则您会发现它们很难被识别。可以用其他同名替换它们,但可靠地添加新的表单元素是您不需要的麻烦。

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

效果很好,就像这样:

...从年份开始选择

您的 myajax 函数只是替换 2span.innerHTML= 无论您的 php 发送什么...

不过,我可以建议您将解决方案扩展到使用图形 UI。最简单的版本是年、月和日期按钮。 HTML5 甚至可以为您动态绘制它们。您可以使用 ajax 来灰显或隐藏对给定年份选择无效的任何按钮。毕竟,返回大量按钮代码就像选择语句一样容易。只需在生成按钮时设置 onClick='myajax(\"whatever\")'。

【讨论】:

【参考方案4】:

我有类似的情况,我相信您需要根据数据库中的值创建月份和日期选择,您可以使用 php 函数 date 例如 &lt;option&gt; echo date(d,Var) - 假设 var 是日期从数据库是 = 01/05/2013,在这种情况下,您的选项将是 '01',在月份的情况下使用 &lt;option&gt; echo date(F,Var) 在这种情况下,选项是 'May' 等等。

准备一个查询以列出所有报告日期,然后从查询中选择它们并将它们填充到您的选择中。

检查PHP date function。

这是当前的JSFiddle

【讨论】:

如何将用户在年份中选择的内容提交回数据库以查询月份(并非所有月份都有报告)。我知道如何编写 SQL,但我不知道如何让 ajax 获取值 onChange 并将其发送到数据库。 你考虑过使用&lt;input type ="date"&gt; 我不明白你的评论。在 JSFiddle 中,html 是静态的,但实际上月份和日期选择将根据用户选择的内容动态填充,因此我认为 ajax 最好将用户选择的内容发送回查询我的数据库表。我不知道如何将值放入变量并编写ajax。 我明白你的意思,这需要先设置一些逻辑,但是为什么不允许用户输入任何日期,然后如果数据存在则显示该日期的报告,否则显示一条消息,指出没有可用的信息。 我越来越近了,但我的函数 dates() 不起作用。尝试获取所有值并连接到输入文本字段中,我将隐藏并使用它来提交。应该是这样的日期:07/12/2013。见 JSFiddle - jsfiddle.net/sloga/KdskX/17【参考方案5】:

我已经做了很多类似的解决方案。一个很好的想法是保存在变量中选择的日期。因此,当您更改其中一个字段时,其对应的变量将使用其选择的值进行更新。在更改任何选择框时,所有其他选择框都通过 ajax 单独更新,所有变量都作为哈希发送。这解决了在单独选择时更新内容的许多问题。

如果用户朝“正确”的方向前进,则没有问题,如果他或她“返回”,则会出现问题......以上解决了这个问题。

【讨论】:

这是我一直在尝试的,但我不确定如何编写 ajax。【参考方案6】:
<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>

【讨论】:

以上是关于根据之前的下拉选择动态填充多达 3 个下拉列表的主要内容,如果未能解决你的问题,请参考以下文章

如何根据使用 jQuery/AJAX 和 PHP/MySQL 选择的第一个下拉列表填充第二个下拉列表?

根据下拉选择创建动态下拉选项 - 卡住

根据第一个下拉选择填充第二个下拉列表

根据第一个选择动态填充第二个下拉菜单

python GAE中的动态下拉列表

根据另一个下拉列表中的选择填充一个下拉列表,然后重定向