bootstrap下拉框分页_【Bootstrap】 bootstrap-select2下拉菜单插件
這次開發了個小TRS系統,雖然是很小,但是作為初心者,第一次用到了很多看起來洋氣使用起來有相對簡單的各種前端(主要是和bootstrap配合使用)組件。包括bootstrap-select2,bootstrap-datetimepicker,bootstrap-fileinput等。本文就旨在記錄一些這些組件相關的內容
【bootstrap-select2】
官方文檔:【https://select2.org/options】
這個組件主要用于優化等頁面組件。比如我們想要在下拉菜單的頂部加上一個搜索框支持我們對選項進行搜索,抑或是在多選下拉菜單中我們要有那種類似于tag形式的表現,用這個組件就很好了。首先是這個組件需要在頁面中進行引入的文件:
zh-CN.js是語言翻譯文件,需要注意引入必須在select2.min.js后面,否則會報錯。這一點也適用于絕大多數支持國際化顯示的組件。
當然因為是bootstrap的組件,自然是不能少bootstrap的js和css以及支持bootstrap的jquery了,這個就不寫出來了。
■ 帶靜態搜索框的下拉菜單
所謂靜態搜索框,就是指這個下拉菜單里所有的option都是在頁面渲染時就已經固化好了的,用這個搜索框進行搜索時不會動態發請求到后臺去取數據。這個搜索框的HTML可以這么寫:
1
2
3
這就是一個普通的select,只不過需要有form-control這個class和一個用于后續表示用的id。
然后在js中這么寫:
$('#static_dropdown').select2({
language: 'zh-CN',
width: '100%',
placeholder: '請選擇',
minimumInputLength: 10});
利用前端組件一個非常重要的內容就是把握初始化時各個初始化參數的含義。通過對不同參數發出調整來搞出一個符合自己需求的組件。
這里用到的四個參數,language顯而易見是國際化顯示用的。width指出了這個select的寬度,placeholder就是placeholder...,minimunInputLength指出了在搜索時至少要輸入多少字符才會給出響應的搜索結果。如果待選項不是太多的話盡量不要設置過大的值,像示例的10,我覺得是很大的一個值了。。
下面也會零散性地給出一些參數說明:
selectOnClose 當設置成true時,當收起菜單時的高亮項會自動被選擇,如果是false則不會自動選擇。
dropdownParent 可以指定下拉菜單在html代碼中的位置。默認情況下,下拉菜單都是被append到body中,并且被設置成position:absolute,且位置在select的下方。而設置這個參數比如dropdownParent: $('#myModal'),就可以將下拉菜單放入一個指定的容器中。
tags 把tags設置成true了之后,在搜索時即便沒有搜索到相關內容,也會把你輸入的內容當成一個可選項。之所以被稱為tags,就是因為tags這個東西不一定要都是既存的,可以有非既存而我們自己添加的情況。
placeholder 如果值是一個字符串那么就是一個簡單的placeholder,如果換成一個對象也可以,即為菜單添加一個默認的選項。比如placeholder: {id:-1,text:'--請選擇--'}
tokenSeparators 可以設置成一個包含各種字符的列表如[',',' '],常和tags以及多選菜單配合使用。即自己輸入時,輸入逗號或空格(看你這個參數設置的情況)時認為是一個tag的終結,就把前面的內容作為一個新tag添加到多選框里面。
createTag 這個參數的值也是一個函數對象。這個函數接受一個參數param,其結構是這樣的
我們主要關注term這一項的值,我們可以在createTag指定的函數中對term進行一些邏輯判斷和處理,然后返回一些結果來讓添加標簽的過程更加智能化一些。比如:
$('#testselect').select2({
createTag: function(param){
var term =$.trim(param.term);
if (term.indexOf('@') == -1){
return null;
}
else{
var id = term.split('@')[0];
var text = term.split('@')[1];
return{id:id,text:text};
}
}
});
在用戶輸入自定義的tag的時候可以檢查存不存在@,如果不就不允許其增加這個tag,如果存在則@前面的部分作為value,后面的部分作為的text,加入一個新的tag。
minimunResultsForSearch 通常這個參數設置成一個整數,當option的待選數量大于這數字時才顯示搜索框。當把這個參數設置為Infinity時將默認不顯示搜索框即禁用搜索框。這樣select就變成了一個simple的select了。
maximumSelectionLength 若是多選框,設置最多可以選擇幾項
另外,可以在select和option中引入一層optgroup標簽并設置其label屬性。optgroup可以為所有選項劃分出合適的組分并且顯示以label的標簽。將option的disabled設置為disabled還可以禁止選擇某一個選項。
●? 帶有圖片的下拉菜單
上面的說明,得到的下拉菜單都是純文字的。其實select2支持我們傳遞圖片進去作為每個選項的一個修飾。這里就要用到templateResult這個參數。
首先要明確,我們雖然在html上寫的是select和option,但是最終經過select2的加工呈現出來的是ul和li,每個li里面是當時option中的內容。在了解這一點的基礎上,我們的templateResult參數是一個函數對象。這個函數對象接受一個object(這個object八成是select2內部定義的抽象了菜單選項的object)為參數并且返回字符串或jquery對象供select2渲染成菜單選項。簡單來說,就是select2會對所有選項進行一個遍歷,依次執行一下這個函數然后按照我們定義的方式渲染出我們想要的菜單選項的樣式和內容。比如下面這樣:
templateResult: function(row){
return $(''+row.text+'');
}
上面這個函數有點繞,簡單來說就是可以把/static/img/.png作為標識圖片放在option的旁邊。如果在這個函數中斷點看下row的具體情況的話,就可以看到其實這個row的結構是這樣的:
Object { selected: false, disabled: false, text: "張三", id: "10001", title: "", _resultId: "select2-addTrainSpeaker-result-5o5i-10001", element: option }
也就是說我們的option的value在這里是id,option的字符串在這里是text,這樣就可以根據value和字符串來定制了。順便一提,上面的函數中return要加上$()是因為不這樣返回的默認是字符串,也就是每一項的內容都會變成xxxx的樣子而不是html內容。所以返回jquery對象比較靠譜。
在編寫templateResult函數的時候,還要注意對loading狀態的處理。當打開下拉列表時,最先進入這個函數的應該是loading狀態的對象,此時row沒有id屬性,當時有loading:true屬性,如果此時不返回當前的row.text(正在加載中之類的提示文字)的話,渲染有可能就停止在這步。所以一般而言可以在templateResult函數里寫上if(row.loading){return row.text;}之類的邏輯。
■ tag形式的多選框
所謂tag形式的多選框就是指這種:
這個看起來比較復雜,其實也通過select2實現也比較方便。html可以這么寫:
+
a
b
c
然后在js中這樣寫:
var multiple = $('#multiple_choice').select2({
placeholder: '請選擇',
allowClear: true});
$('#multiple_all').click(function(event){
event.preventDefault();
var res =[];
$(this).next('select').find('option').each(function(i,ele){
res.push($(ele).val())
});
$(multiple).val(res).trigger('change');
});
第一部分很好理解,和上面的下拉菜單一樣,也是初始化。只是這個初始化返回了一個jquery對象,我們先用multiple這個變量保存下來。然后當select前面的那個按鈕被點擊時,就是執行了第二部分代碼,是將select中所有選項的值都加入到一個數組中,然后把這個數組傳遞給剛才那個multiple對象的val方法,再trigger一下change事件。這樣就可以自動地選擇所有選項到多選框里面了。(這部分是我自己加上去,不是select2要求的)。
可以看出來$(multiple).val(xxx).trigger('change')就是拿來引發多選框被選中值變化的方法。如果xxx處填寫null那么就是清空多選框了。
關于如何取值,類似的我們可以$('#multiple_choice').val()來取值,得到的應該是一個數組。這里多提一句,如何通過ajax傳遞數組給后臺。直接寫入ajax方法的data字段需要特殊處理過的數組。比如我們有數組對象array想要作為參數parti的值通過ajax傳遞出去的話,那么可以先JSON.stringify(array),得到的json化的字符串再拿來傳遞即可。在后臺我們只要用相關后臺的方法來解析json格式字符串即可。
■ 編程控制
上面提到了如何一鍵清空或全選多選框的選項、這個其實是一個select2組件的編程控制。更一般地來說我們可以這樣給下拉菜單多增加一個選項:
var data ={
id: 1,
text: 'test'};
var newOption = new Option(data.text,data.id,false,false);
$('#testselect').append(newOption).trigger('change');
如果是選取若干個可以傳遞一個數組給val方法。如果需要對待加入項是否已經存在做出判斷的話可以這么做:
if ($('#testselect').find('option[value='+data.id+']').length){
$('#testselect').val(data.id).trigger('change'); //如果已經存在則不添加而是選擇那一項
}
else{
var newOption = new Option(data.id,data.text,true,true);
$('#testselect').append(newOption).trigger('change');
}
■ 動態搜索下拉菜單
所謂動態,即每次搜索框中數據發生變化時,前端會向后臺發送ajax請求來獲取一些數據,把這些數據用于填充下拉菜單的內容。實現方法是在初始化select2組件的時候加入ajax參數,如:
$('#testselect').select2({
ajax : {
url: '/api',
dataType: 'json', //比較重要,沒有的話返回json數據會無法識別,搜索失敗
data: function(param){
return{
keyword: param.term,
searchType: 'public',
page: param.page || 1}
}
}
})
ajax參數的值是一個object,包括url等key。url這個肯定是要有的,指出了ajax請求發往什么地方。data參數是可選的,在默認情況下select2發出的請求包含了以下幾個參數:
term 此時搜索框中的內容
q 和term內容一樣
_type 通常是query,如果涉及到結果分頁時可能不一樣
page 當有結果分頁時有此參數,指出當前分頁
*關于分頁和page參數:在當前處于默認第一頁的時候,發送的請求不帶page參數,所以一般來說我們都會在data參數的函數對象中對page參數做這樣一個處理: params.page = params.page || 1;來保證第一次打開輸入框時也會給出page=1作為請求參數。
在設置data參數之后,data參數的值是一個獲取當前搜索框中對象(具體搜索內容是其term參數)并返回一個object作為ajax參數的函數對象,我們可以借此來定義一些自定義的請求參數字段。
需要特別說明的是,這里的ajax請求默認是get方法,目前還沒找到如何改成post的辦法。
因為前端會自動對后端傳遞過來的數據進行適應select2組件的渲染,所以其對于數據的格式肯定是有要求的。具體的要求是這樣的:
{
results: [
{id: '10001', text: 'Option_1'},
{id: '10002', text: 'Option_2'},
//等等,這部分就是主要的數據
],
pagination: {
more: true}
}
主要數據部分每個列表項都是一個object且包含id和text兩個字段分別用來填充option標簽對應的那兩個字段。pagination則是指出了前端會對上送的結果做一個分頁處理,即一次性只在下拉列表中顯示有限個項,但在最下方有一個“顯示更多項”,當滾動條到最下方時再自動發送請求去調取下一個分頁的數據。當然,順利地實現分頁需要前端發出的ajax請求中帶有param.page這個信息(如上上面的代碼所示),然后后端也要根據上送上來的page的值來進行相應數據段的返回。前后端協調了才可以給出比較好的分頁效果。
上面的說明中可以看得出對數據格式要求比較嚴格(results,pagination,id,text等字段都不能自定義),為了適應更加多樣化的形式的數據,我們可以在ajax參數中再加上一個processResults字段:
$('#testselect').select2({
ajax: {
url: '/api',
dataType: 'json',
data: function(param){
return{
kw: param.term,
page: param.page || 1
};
},
processResults: function(data){
return{
results: data.items
};
}
}
})
上面的示例雖然有了分頁,不過還有個小瑕疵,就是即使加載完了所有數據,最下面的加載所有數據依然會存在而不消失。這個問題可以在前端解決,官方文檔中給出的示例是這樣的:
processResults: function(data,params){
params.page = params.page || 1;
return{
results: data.results,
pagination: {
more: (params.page * 10)
}
};
}
首先,返回的結果中多了一個total_count字段,它指出了未分頁時結果集的個數。注意是未分頁時,即搜索條件不變時不論page是多少這個字段的值是不變的。然后在后端返回中的pagination字段可以去掉了,因為這個字段通過前端的邏輯判斷來置true或false,這個條件,就是上面寫著的當前頁面*10是否小于總條數(也就是一次顯示10條)。若否,表明已經加載到了最后一頁,此時pagination就可以是false,即不需要再顯示“加載更多數據”了。
需要額外說一下,分頁的個數最好要達到5個以上才會有正常的效果。我嘗試了一次分頁只給出兩三個結果的時候,前端頁面會一直顯示在加載更多結果但是沒有真的在加載數據
●? 更多ajax參數
delay 可以在ajax的參數中加上delay,取值單位是毫秒。意思是說當用戶停止輸入了這么多毫秒之后再發出ajax請求。用戶每改動一個字母就發出一次請求顯然是比較浪費資源的,這么做更加合理一些。
■ 設置選擇框的默認值
對于靜態框,我們可以在生成之后通過$(element).val([...]).trigger('change')的辦法來為select2渲染出來的東西添加一個或一些默認選中的值。如果一定要在初始化的時候就設置好默認的值那么也可以利用placeholder這個初始化參數。正如上面所說,如果placeholder是個字符串那么就是普通的placeholder,但如果是個object那么將會是一個提示默認選擇值的東西。
對于有ajax參數的動態選擇框有些復雜。我在實踐中找到了一種方法。我們知道,構造一個動態的選擇框是不需要在select標簽中添加option的,但是即便我們あえて添加一些的話,渲染出來的動態框,我們打開選擇框也不會出現那個預設的靜態選項。不過它有一個用,就是可以被val([xxx]).trigger('change')這個操作捕捉到。
也就是說,如果我們想對一個動態框預設一個或幾個選中值(通常這些值應該也是我們預期能夠通過動態框獲取到的值),我們可以首先假裝它是一個靜態選項,作為寫死到中去,然后再通過val([...]).trigger('change')將這些所謂的靜態選項置選中。事實上這些所謂的靜態選項并不會出現在選擇框中,而靜態的和val/trigger兩者的交集會作為最終被選中的默認值。
示例:
Preselected Value 1
Preselected Value 2
//js中
$('#test').select2({
ajax: {...}//構造了一個動態的選擇框
}).val(['0','1']).trigger('change');
然后頁面上的這個多選框就是默認選中了Preselected Value1和Preselected Value2兩個選項(不管ajax請求發出之后能否真的能獲取到這兩個選項)
總結
以上是生活随笔為你收集整理的bootstrap下拉框分页_【Bootstrap】 bootstrap-select2下拉菜单插件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: matlab中noisbloc,基于小波
- 下一篇: fanuc roboguide_ROBO