下拉表關聯非同步載入不是事兒 - 引數動態過濾
對於報表,簡單來說就是用表格、圖表等格式來動態顯示資料以及資料之間的關係,同時,經常伴隨的,也是很重要的一個功能就是給報表增加各種條件,對資料進行篩選,以便找出使用者最關心的資料。
篩選條件常常不止一項,也就是我們常說的多條件查詢,同時這些條件之間可能還有關聯關係,比如最常見的“省份”和“城市”之間,在選擇了“省份”後,“城市”選項應該只顯示當前省下的列表。這種情況,我們一般會用關聯過濾來進行處理。
對於省份和城市,這個例子本身資料量就不大(一個省份下城市多的也就 4、50,全國也不過千把個城市),採用報表工具編輯風格內的關聯過濾(資料全記憶體,頁面操作時再去過濾)解決也就是分分鐘的事兒。
但是問題來了,如果資料大到一定程度呢?
比如,同樣很常見的“產品類別”與“產品名稱”之間的關聯過濾,想象一個全國性的海鮮交易集散地,單拿出一個類別“水產品”來說,僅僅叫 xx 魚的就會有 2 萬餘種,要是再加貝類、甲殼類等呢?! 如果再算上農副產品,更不要說還有酒類、飲料類、調味品類……
於是,結果就是:
您沒看錯,就只能等待、等待……再等待!因為下拉框要載入半天,只能等頁面載入完再操作。對於報表使用者來說,看得到的是報表系統效率極低,而看不到的則是記憶體佔用極大,導致整個系統受到影響。這樣,僅僅因為想看一眼可能會用到的某個產品,就需要把所有的拿出來等待“出臺”……所以,經常是還沒看到報表呢,頁面卡死了,然後就沒有然後了,只能開始罵人了。
所幸,對於程式猿來說,知道有個好玩意叫非同步載入,也就是可以根據選的值動態去資料庫裡或其他資料來源查後再頁面載入(也就是不用全查出來放在記憶體“備用”了)。
還是拿產品類別和名稱的聯動舉例,用上非同步載入,初始載入引數表單時只需載入產品類別就可以了,選定哪個類別後再去庫裡查對應的產品名稱列表,這樣就做到了用誰查誰、頁面載入誰,從此記憶體用起來也不那麼心疼了、頁面載入也不再力不從心了。
好了,囉嗦這麼些,在潤乾報表中到底是怎麼實現非同步載入的呢?
官方功能說明:
1、設計器設計引數表單,假如有兩個下拉資料表A、B,分別對應引數arg1、arg2,選擇A以後過濾B。設計時A設計完整,B可以設計時加一個過濾條件讓它取不到數或資料特少。
2、在顯示引數表單的jsp裡,使用者寫一個下面這樣的js函式,這是下拉表選擇後會呼叫的js函式,cellId是下拉控制元件所在單元格id,newValue是新的下拉值, argName是引數名
function _selectValueChanged( cellId,newValue, argName ) {
if(argName == "productTypes" ) {
varparams = { "arg1": newValue };
$.post(url, params, function( data ) {
data= eval( "(" + data.trim() + ")" );
$("#arg2").combobox("loadData", data ); //將新的節點資料設定到arg2
},"text");
}
*}
示例中的url是伺服器上的一個servlet或jsp等服務程式, 根據ajax傳上去的引數params,為arg2取回新的資料,資料的格式如下:*
\[{ v:"v1",d:"選項1"},{ v:"v2",d:"選項2"},......,{v:"vn",d:"選項n"}\]
v表示真實值,d表示顯示值
接下來結合例項來看下具體的做法:
1、準備一個引數表單和結果報表
(1)引數表單:產品類別(web 名:productTypes)、產品名稱(productName)
選擇產品類別 (如 1- 飲料;2- 調味品;3- 其他) 後, 後臺計算對應的可選產品名稱列表並返回給下拉列表
(2)結果報表僅演示接收兩個條件值
2、Jsp 內定義上面 2(功能說明)中的方法
function_selectValueChanged( cellId, newValue, argName ) {
//如果是productTypes下拉,則觸發
if( argName == "productTypes" ) {
varurl = "rv.jsp";//非同步請求的伺服器檔案,此處為jsp
var params = { "productTypes":newValue };
$.post( url, params, function( data ) {
alert(data);
data = eval( "(" +data.trim() + ")" );
$("#productName").combobox("loadData", data ); //將新的節點資料設定到productName下拉項
}, "text");
}
}
3、定義非同步處理資料的服務地址(jsp 或 servlet 等)
看上一步 url 為 rv.jsp(與展現報表的 jsp 同目錄),核心程式碼:
<%@ page contentType="text/html;charset=UTF-8" %>
<%
String proType = request.getParameter("productTypes");
String strv = "";
if("1".equals(proType)){
strv = "\[{v:'1',d:'純淨水'},{v:'1',d:'礦泉水'},{v:'1',d:'橙汁'},{v:'1',d:'桃汁'}\]";
}else if("2".equals(proType)){
strv = "\[{v:'2',d:'米醋'},{v:'2',d:'精鹽'},{v:'2',d:'味精'},{v:'2',d:'花椒粉'}\]";
}else if("3".equals(proType)){
strv = "\[{v:'3',d:'3333'}\]";
}else{
strv = "\[{v:'10010',d:'other ans'}\]";
}
out.print(strv);
%>
<!—程式碼可以看出,根據接收類別的不同,返回不同資料列表。同理,如果是要經過資料庫查詢,按條件執行不同sql即可-->
4、看效果
通過上面的替換,從而實現當“產品類別”選擇為“1”(飲料)時,則“產品名稱”僅可選擇 “純淨水”、“礦泉水”等飲料類產品。
產品類別為“2”(調味品)時,則只能選擇“精鹽”、“醋”等。
通過這個例子可以看到,在潤乾報表中實現非同步載入資料並不是很複雜的事情,而通過這種方式可以有效地提高關聯過濾的輸入效率,為使用者提供更好的體驗,延長了滑鼠、鍵盤的使用壽命,減少了開發者被問候而打噴嚏的機會……
當然,除了這種“高大上”的關聯過濾方式,潤乾報表本身也提供了相對簡單、不用考慮太多因素(比如資料量過大,造成記憶體過多佔用等)的關聯過濾功能,以及基於 sql 就可以處理的非同步載入功能。
至於怎麼選麼??答案是:看實際情況(這個回答不會捱揍吧),或者諮詢支援人員(企業 QQ:800025723)。