2011年3月7日 星期一

使用 jQuery 讓 DropDownList 的值動態依據條件來顯示

有個需求,希望 DropDownList 裡面的值,可以依據 check box 的條件,動態去更新。以下圖來說,當 check box 條件沒有勾選時,DropDownList 的值一共有:請選擇、A、B、C 四個選項。但當 check box 條件勾選了 c2,c3 時,則 DropDownList 的值只剩下:請選擇、B、C 三個選項。用 jQuery 來練習一下...

這次,我用到了 jQuery 的 remove() 與 append() 兩個方法。每當 check box 觸發了 click 事件,我就先用 remove() 清除掉目前 DropDownList 裡的所有值,並依據 check box 的勾選條件來將 DropDownList 裡的選項一一透過 append() 方法來加入。

<!DOCTYPE html>
<html>
<head>
  <script src="http://code.jquery.com/jquery-1.5.js"></script>
  <script>

//設定結果清單
function SettingCheckItems()
{ 
 //移除所有結果
 $("#sel > option").remove();

 //先新增第一個結果:「請選擇」
 $("#sel").append('');

 //如果條件有勾選 c1,則結果新增一個 c1
 if($("input[type=checkbox][name=c1]:checked").length>0)
  $("#sel").append('');

 //如果條件有勾選 c2,則結果新增一個 c2
 if($("input[type=checkbox][name=c2]:checked").length>0)
  $("#sel").append('');

 //如果條件有勾選 c3,則結果新增一個 c3
 if($("input[type=checkbox][name=c3]:checked").length>0)
  $("#sel").append('');

 //如果都沒有勾選任何條件,則將所有結果都列出
 if($("input[type=checkbox]:checked").length==0)
 {
  $("#sel").append('');
  $("#sel").append('');
  $("#sel").append('');
 } 

}


  $(function(){
 //畫面初始時,先執行結果的設定
 SettingCheckItems();

 //如果條件的 checkbox 有被異動,則設定結果清單
 $("input[type=checkbox]").click(function(){ 
  SettingCheckItems();
        });
  });

  </script>
</head>
<body>

  條件:
  <input type="checkbox" name="c1" value="c1">c1
  <input type="checkbox" name="c2" value="c2">c2
  <input type="checkbox" name="c3" value="c3">c3   結果:
  <select id="sel" >
  <option value="" >請選擇</option>  
  </select>

</body>
</html>

如果不打算用 ASP.Net 來撰寫,程式到此應該算是完成了。只是當我用 ASP.Net 改寫時,遇到了沒有預期的錯誤訊息。我使用了 <asp:CheckBoxList /> <asp:DropDownList /> ,並加上一個會觸發 postback 的 Button 來顯示目前所挑選的結果值,沒想到卻出現了一個錯誤訊息:

 Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

原來 asp.net 在每一次的 postback 會去呼叫  EventValidation,而  EventValidation 則是將每一次 Render 畫面時的控制項與值都會記錄下來,並且去與上一次比較是否有所不同。這個用意,是為了提高網站的安全性,避免被攻擊的疑慮。但由於我透過 DOM 的操作,去增加或減少了頁面的 DOM 項目,當然與 EventValidation 的設計有所違背,所以會出現上面的錯誤訊息。

而微軟似乎也沒這麼霸道,提供了兩個選擇,第一,就是關掉 EventValidation 的驗證。但缺點就是會降低網頁的安全性。第二,使用 ClientScriptManager 去寫RegisterForEventValidation 方法,這似乎是個解決方法,但...好麻煩。 最簡單的方法,就是,不要用。是指不要用 <asp:DropDownList />,而是改用 <select id="sel" runat="server> 的方式。日後要抓下拉清單所挑選的值時,就使用 Request.Form["sel"] 。

改完後的 ASP.Net 版如下:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm4.aspx.cs" Inherits="WebTest.WebForm4" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://code.jquery.com/jquery-1.5.js"></script>
    <script>
        //設定結果清單
        function SettingCheckItems() {
            alert('t');
            //移除所有結果
            $("select[id*=sel] > option").remove();

            //先新增第一個結果:「請選擇」
            $("select[id*=sel]").append('');

            //如果條件有勾選 c1,則結果新增一個 c1
            if ($("input[type=checkbox][value=c1]:checked").length > 0)
                $("select[id*=sel]").append('');

            //如果條件有勾選 c2,則結果新增一個 c2
            if ($("input[type=checkbox][value=c2]:checked").length > 0)
                $("select[id*=sel]").append('');

            //如果條件有勾選 c3,則結果新增一個 c3
            if ($("input[type=checkbox][value=c3]:checked").length > 0)
                $("select[id*=sel]").append('');

            //如果都沒有勾選任何條件,則將所有結果都列出
            if ($("input[type=checkbox]:checked").length == 0) {
                $("select[id*=sel]").append('');
                $("select[id*=sel]").append('');
                $("select[id*=sel]").append('');
            }

        }

        $(function () {
            //畫面初始時,先執行結果的設定
            SettingCheckItems();

            //如果條件的 checkbox 有被異動,則設定結果清單
            $("input[type=checkbox]").click(function () {
                SettingCheckItems();
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    條件:
        <asp:CheckBoxList ID="cb" runat="server" RepeatDirection="Horizontal" 
            RepeatLayout="Flow">
            <asp:ListItem>c1</asp:ListItem>
            <asp:ListItem>c2</asp:ListItem>
            <asp:ListItem>c3</asp:ListItem>
        </asp:CheckBoxList>
    
      結果:
    <select id="sel" runat="server"></select>
    
    
     
        <asp:Button ID="btnCommit" runat="server" onclick="btnCommit_Click" 
            Text="Commit" />
    
    </div>
    </form>
</body>
</html>


後記:今天在查 jQuery 文件時,發現他的版本已經到 1.5.1 了,新增了許多好玩的地方,有空可以上去瞧瞧囉。

參考:getting exception if the dropdowns are binded with DHTML in the grid

沒有留言:

張貼留言