引用網址:http://www.misterngan.com/883/jqgrid-%E5%AF%A6%E7%94%A8%E6%8A%80%E5%B7%A7-%E4%B8%89-form-search/

話 說 jqGrid 的 偉 大 之 處 ,就 是 Form Editing。它 令 jqGrid 可 以 自 動 生 成 不 同 種 類 的 Form,今 天 為 大 家 介 紹 幾 個 Form Search 的 技 巧 。因 為 想 討 論 得 深 入 一 點 ,所 以 範 圍 限 定 在 最 簡 單 的 Single Search。

首 先 的 當 然 還 是 colModel,先 用 比 較 簡 單 的 資 產 名 稱 作 為 例 子 。

$("#list").jqGrid({
url: 'data_json.php'
....
colModel :[
....
{name:'asset_name', index:'asset_name', search:true, stype:'text', searchrules:{required:true}, searchoptions:{sopt:['eq','cn','bw','ew']}},
....
],
....
});

search:true,這 很 明 顯 ,就 是 可 以 搜 尋 的 意 思 ,false 就 當 然 是 相 反 。但 有 一 點 要 注 意 ,如 果 欄 位 是 隱 藏 的 (即 hidden:true),那 該 欄 位 也 是 不 能 搜 尋 的 。

stype 用 了 text,意 思 就 是 會 出 現 一 個 text input 給 使 用 輸 入 資 料 。stype 可 以 是 text 或 者 select。

searchoptions 的 sopt,讓 我 們 可 以 選 擇 搜 尋 時 的 比 對 方 法 ,上 例 中 順 序 是 ‘equal’, ‘contains’, ‘begins with’, ‘ends with’,就 是 一 般 文 字 資 料 的 搜 尋 方 法 。另 外 還 可 以 有 ‘not equal’, ‘less’, ‘less or equal’, ‘greater’, ‘greater or equal’ 等 等 。但 重 點 是 你 可 以 針 對 每 一 個 欄 位 的 屬 性 自 定 搜 尋 的 比 對 方 法 。

searchrules 裡 面 的 required,意 思 就 是 必 須 要 輸 入 資 料 ,就 是 說 如 果 使 用 沒 有 輸 入 資 料 ,jqGrid 就 會 顯 示 一 個 錯 誤 訊 息 。因 為 使 用 者 不 應 該 去 搜 尋 名 稱 為 空 白 的 資 產 吧 ?

simple single search

在 進 一 步 討 論 更 複 雜 的 colModel 之 前 ,讓 我 們 稍 為 窺 探 一 下 jqGrid search 的 時 候 在 伺 服 器 端 的 作 法 。因 為 很 多 時 候 ,資 料 庫 都 會 很 大 ,有 很 多 筆 的 資 料 ,所 以 我 們 不 會 一 次 過 把 數 萬 筆 的 資 料 都 下 載 到 使 用 者 的 電 腦 ,再 用 它 們 建 構 一 個 超 大 型 的 grid。相 反 的 ,我 們 每 一 次 只 會 讀 取 剛 好 足 夠 的 資 料 ,通 常 一 次 讀 取 一 頁 的 資 料 就 足 夠 了 。

這 件 事 就 是 我 們 後 台 的 php 所 做 的 事 。jqGrid 的 php 範 例 寫 得 簡 單 明 瞭 ,絕 大 部 分 的 情 況 下 都 夠 用 了 。但 它 卻 沒 有 在 伺 服 器 端 做 search 的 例 子 ,令 部 分 用 家 有 一 點 困 惑 。我 在 這 裡 就 教 大 家 做 一 個 簡 單 的 single search 都 可 以 通 用 的 例 子 。下 面 的 程 式 碼 是 用 php 寫 的 ,就 是 上 面 例 子 中 的 data_json.php。

在 原 來 的 例 子 ,有 兩 句 sql。一 句 是 SELECT count(*) 的 ,用 來 取 得 所 有 資 料 的 筆 數 ,再 用 來 計 算 jqGrid 的 總 頁 數 。第 二 句 SELECT fields FROM table ORDER BY $sidx $sord LIMIT $start , $limit,這 是 用 來 取 得 本 頁 的 資 料 的 。

$SQL1 = "SELECT COUNT(*) AS count FROM assets";
$SQL2 = "SELECT * FROM assets ORDER BY $sidx $sord LIMIT $start , $limit";

我 們 要 為 它 們 加 上 一 個 條 件 式 。

$SQL1 = "SELECT COUNT(*) AS count FROM assets WHERE $condition";
$SQL2 = "SELECT * FROM assets WHERE $condition ORDER BY $sidx $sord LIMIT $start , $limit";

那 條 件 或 要 怎 麼 設 定 呢 ?那 要 在 php 檔 開 頭 的 地 方 。其 實 jqGrid 做 search 的 時 候 ,它 會 將 一 些 變 數 傳 回 到 伺 服 器 端 ,我 們 要 做 的 就 是 取 得 這 些 變 數 ,再 建 構 用 於 sql 句 子 的 where condition。

$condition = 1;

if (isset($_GET['_search'])) {

    if ($_GET['_search']<>'false'){

    $searchField = $_GET['searchField'];
    $searchOper = $_GET['searchOper'];
    $searchString = $_GET['searchString'];

    switch ($searchOper) {
        case "eq":
            $condition .= " AND ".$searchField;
            $condition .= " =";
            $condition .= " '".$searchString."'";
            break;
        case "ne":
            $condition .= " AND ".$searchField;
            $condition .= " <>";
            $condition .= " '".$searchString."'";
            break;
        case "bw":
            $condition .= " AND ".$searchField;
            $condition .= " LIKE";
            $condition .= " '".$searchString."%'";
            break;
        case "bn":
            $condition .= " AND ".$searchField;
            $condition .= " NOT LIKE";
            $condition .= " '".$searchString."%'";
            break;
        case "ew":
            $condition .= " AND ".$searchField;
            $condition .= " LIKE";
            $condition .= " '%".$searchString."'";
            break;
        case "en":
            $condition .= " AND ".$searchField;
            $condition .= " NOT LIKE";
            $condition .= " '%".$searchString."'";
            break;
        case "cn":
            $condition .= " AND ".$searchField;
            $condition .= " LIKE";
            $condition .= " '%".$searchString."%'";
            break;
        case "nc":
            $condition .= " AND ".$searchField;
            $condition .= " NOT LIKE";
            $condition .= " '%".$searchString."%'";
            break;
        case "nu":
            $condition .= " AND ".$searchField;
            $condition .= " IS NULL";
            break;
        case "nn":
            $condition .= " AND ".$searchField;
            $condition .= " IS NOT NULL";
            break;
        case "in":
            $condition .= " AND ".$searchField;
            $condition .= " IN";
            $condition .= " ('".$searchString."')";
            break;
        case "ni":
            $condition .= " AND ".$searchField;
            $condition .= " NOT IN";
            $condition .= " ('".$searchString."')";
            break;
        case "lt":
            $condition .= " AND ".$searchField;
            $condition .= " <";
            $condition .= " '".$searchString."'";
            break;
        case "le":
            $condition .= " AND ".$searchField;
            $condition .= " <=";
            $condition .= " '".$searchString."'";
            break;
        case "gt":
            $condition .= " AND ".$searchField;
            $condition .= " >";
            $condition .= " '".$searchString."'";
            break;
        case "ge":
            $condition .= " AND ".$searchField;
            $condition .= " >=";
            $condition .= " '".$searchString."'";
            break;
    }   

    }
}

一 開 始 的 $condition = 1 的 意 思 就 是 所 有 資 料 。SELECT * FROM table WHERE 1 ,就 是 所 有 資 料 了 。而 當 前 台 傳 來 要 求 的 時 候 ,如 果 _search 變 數 不 是 false,我 們 就 開 始 加 入 要 搜 尋 的 條 件 。Single Search 的 情 況 ,每 次 只 會 搜 查 一 個 欄 位 。於 是 我 們 簡 單 地 用 switch 來 辨 別 不 同 的 searchoper ,再 從 而 構 成 我 們 的 $condition。$condition 的 樣 子 就 會 像 :1 AND asset_name=’123’。

筆 者 上 面 的 例 子 只 適 合 一 般 情 況 使 用 ,你 很 可 能 需 要 為 你 自 己 的 需 要 而 作 出 修 改 。千 萬 記 住 ,兩 個 select  句 子 都 必 需 要 加 上 相 同 的 condition ,不 然 的 話 ,你 的 分 頁 數 和 你 的 資 料 筆 數 就 會 對 不 上 了 。

好 了 ,回 到 前 台 的 jqGrid 吧 。讓 我 們 看 看 stype=’select’ 是 如 何 做 的 。在 我 的 資 料 庫 中 ,有 一 個 boolean 欄 位 叫 fix_asset,是 代 表 該 筆 資 產 是 不 是 固 定 資 產 。資 料 庫 裡 面 是 用 0 / 1 表 示 。在 jqGrid 顯 示 的 時 候 ,我 把 它 顯 示 成 是 / 否 。於 是 ,在 搜 尋 的 時 候 ,也 相 應 給 使 用 者 選 擇 是 / 否 ,而 不 要 使 用 者 輸 入 0 / 1。

....
{name:'fix_asset', index:'fix_asset', search:true, stype:'select', searchoptions:{value:"0:否 ;1:是 ", sopt:['eq']}, edittype:'select', editoptions:{value:"0:否 ;1:是 "}, formatter:'select'},
....

上 例 之 中 ,edittype, editoption, formatter 三 個 選 項 都 是 為 了 在 grid 裡 面 顯 示 是 /否 的 。只 有 stype 和 searchoptions 才 是 和 search form 有 關 係 的 。由 於 資 料 不 是 0 就 是 1,所 以 sopt 只 要 一 個 equal 就 夠 了 ,什 麼 大 於 小 於 contains 都 是 毫 無 用 處 的 。又 因 為 我 們 用 select 固 定 了 使 用 者 的 輸 入 數 據 ,所 以 也 不 需 要 另 外 做 data validation 了 。

Search Form Select

然 後 我 們 試 試 在 search form 裡 面 加 入 一 個 jQuery UI – datepicker。其 中 一 個 欄 位 叫 purchase_date,正 好 是 日 期 的 資 料 型 態 。這 個 部 分 稍 為 複 雜 一 點 點 ,我 們 要 使 用 到 自 定 義 函 數 。

$("#list").jqGrid({
url: 'data_json.php'
....
colModel :[
....
{name:'purchase_date', index:'purchase_date', search:true, stype:'text', searchoptions:{dataInit:datePick, sopt:['eq','ge','le']}, searchrules:{required:true, date:true} },
....
],
....
});

function datePick(elem){
$(elem).datepicker({ dateFormat: "yy-mm-dd" });
}

先 看 看 colModel,因 為 是 使 用 text input,所 以 使 用 鍵 入 任 何 資 料 也 有 可 能 ,所 以 我 們 可 以 在 searchrules 加 上 data:true,這 樣 的 話 ,jqGrid 就 會 自 動 為 我 們 檢 查 輸 入 資 料 是 否 為 日 子 了 。因 為 資 料 型 態 是 日 期 ,所 以 sopt 就 相 應 的 只 選 擇 了 equal,greater or equal, less or equal 三 種 。要 為 search form 加 入 datapicker,我 們 可 以 在 searchoptions 裡 面 的 dataInit 加 入 一 條 自 定 義 的 函 數 ,我 把 它 叫 做 datePick。在 datePick 函 數 裡 面 ,我 就 為 input element 加 入 datepicker,並 且 把 datepicker 的 dateFormat 設 定 為 符 合 我 的 資 料 庫 使 用 的 日 期 型 態 (就 是 yyyy-mm-dd)。在 香 港 這 種 華 洋 雜 處 的 地 方 ,處 理 日 期 格 式 是 有 點 麻 煩 的 。本 來 從 小 英 式 教 學 都 是 教 dd/mm/yyyy 的 ,但 現 在 社 會 上 使 用 美 式 日 期 mm/dd/yyyy 的 也 不 少 。筆 者 習 慣 是 使 用 yyyy-mm-dd 這 樣 的 格 式 ,那 使 用 者 不 管 是 接 受 英 式 教 育 ,或 者 美 式 教 育 ,甚 至 是 外 國 人 ,也 同 樣 不 會 弄 錯 日 子 了 。

search form datepicker

除 了 datepicker,另 一 個 常 用 的 jQuery UI 就 是 autocomplete。Autocomplete 其 實 和 select 很 類 似 ,但 是 autocomplete 會 自 由 一 點 。一 般 來 說 ,如 果 選 項 是 清 晰 明 確 的 ,而 且 選 項 比 較 少 的 時 候 ,筆 者 會 使 用 select。但 是 如 果 選 項 是 比 較 雜 亂 ,又 或 者 數 量 很 多 的 時 候 ,就 會 使 用 autocomplete。比 如 說 你 有 一 千 個 選 項 ,使 用 select 來 選 其 實 也 很 痛 苦 吧 ?這 時 候 如 果 用 autocomplete 就 可 以 舒 服 很 多 。噢 ,在 這 裡 我 是 說 系 統 使 用 者 舒 不 舒 服 ,而 不 是 系 統 開 發 者 。

$("#list").jqGrid({
url: 'data_json.php'
....
colModel :[
....
{name:'centername', index:'centername', search:true, stype:'text', searchoptions:{dataInit:locationAutocomplete, sopt:['eq','cn']}, searchrules:{required:true} },
....
],
....
});

function locationAutocomplete(elem){
$(elem).autocomplete({
   source:'locationautocomplete.php'
});
}

跟 datepicker 類 似 ,我 們 也 使 用 了 一 條 自 定 義 函 數 locationAutocomplete,同 樣 地 方 在 dataInit 裡 面 。至 於 那 個 autocomplete 的 php 要 怎 麼 寫 ,又 或 者 autocomplete 有 些 什 麼 其 他 設 定 ,在 jQuery 的 網 站 上 就 有 非 常 詳 細 的 解 說 的 了 。

Form search autocomplete

jqGrid search 的 常 用 設 定 還 有 :closeAfterSearch, closeAfterReset, showQuery, closeOnEscape。迢 些 都 是 在 jqGrid 設 定 Navigator 的 時 候 可 以 設 定 的 。這 幾 個 設 定 的 意 思 都 很 直 觀 ,筆 者 就 不 贅 述 了 。

$("#list").jqGrid('navGrid','#pager',
{edit:false,add:false,del:false,search:true,view:false},
{},
{},
{},
{showQuery:true, closeAfterSearch:true, closeAfterReset:true, closeOnEscape:true},
{}
);

再 進 階 的 ,有 Multiple Search,Multiple Group,Custom Search 等 等 ,就 留 待 使 用 者 慢 慢 發 掘 吧 。

arrow
arrow
    文章標籤
    jquery jqGrid
    全站熱搜

    龍之家族 發表在 痞客邦 留言(0) 人氣()