二、導入css和js到網站上
1.使用CDN,節省自己網站的流量
1
2
|
<link href=
"https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.3/css/select2.min.css"
rel=
"external nofollow"
rel=
"stylesheet"
/>
|
2.下載文件到本地,可以做一些個性的定制(比如說修改提示語)
1
2
3
4
5
|
<!-- select2 -->
<link rel=
"stylesheet"
type=
"text/css"
href=
"${ctx}/common/select2/css/select2.css"
rel=
"external nofollow"
/>
<script type=
"text/javascript"
src=
"${ctx}/common/select2/js/select2.full.js"
></script>
<!-- 中文國際化還需要進行參數設置 -->
<script type=
"text/javascript"
src=
"${ctx}/common/select2/js/i18n/zh-CN.js"
></script>
|
三、真刀真槍的干起來
第一步、定制頁面個性化元素
1
2
3
|
<select name=
"parentid"
class=
"js-data-example-ajax"
href=
"${ctx}/member/loadMembersInfo.do?uid=${mem.uid}"
rel=
"external nofollow"
style=
"width:400px"
inputMessage=
"請輸入會員編號(可部分匹配)"
>
<option selected=
"selected"
value=
"666"
>沉默王二</option>
</select>
|
Java端通過name屬性可獲得select的value值。
設置class為js-data-example-ajax,頁面加載時對該組件進行select2的初始化。
href屬性為ajax提供后台檢索的URL。
style設置組件的寬度。
inputMessage屬性定制個性化的提示語,默認的英文版為Please enter 1 or more characters,中文國際化為“請再輸入至少1個字符”,都不太能滿足個性化需求,所以需要改,后面介紹。
提供一個默認的option,頁面沒檢索之前顯示。
第二步、select2組件化,注釋寫得很詳細了哦
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
<script type=
"text/javascript"
>
$(
function
() {
$(
"select.js-data-example-ajax"
).each(
function
() {
var
$
this
= $(
this
);
$
this
.select2({
language :
"zh-CN"
,
// 指定語言為中文,國際化才起效
inputMessage : $
this
.attr(
"inputMessage"
),
// 添加默認參數
ajax : {
url : $
this
.attr(
"href"
),
dataType :
'json'
,
delay : 250,
// 延遲顯示
data :
function
(params) {
return
{
username : params.term,
// 搜索框內輸入的內容,傳遞到Java后端的parameter為username
page : params.page,
// 第幾頁,分頁哦
rows : 10
// 每頁顯示多少行
};
},
// 分頁
processResults :
function
(data, params) {
params.page = params.page || 1;
return
{
results : data.data,
// 后台返回的數據集
pagination : {
more : params.page < data.total
// 總頁數為10,那么1-9頁的時候都可以下拉刷新
}
};
},
cache :
false
},
escapeMarkup :
function
(markup) {
return
markup;
},
// let our custom formatter work
minimumInputLength : 1,
// 最少輸入一個字符才開始檢索
templateResult :
function
(repo) {
// 顯示的結果集格式,這里需要自己寫css樣式,可參照demo
// 正在檢索
if
(repo.loading)
return
repo.text;
var
markup = repo.username;
markup += repo.realname;
var
markup =
"<div class='select2-result-repository clearfix'>"
+
"<div class='select2-result-repository__avatar'><img src='"
+ repo.headimgUrl +
"' /></div>"
+
"<div class='select2-result-repository__meta'>"
+
"<div class='select2-result-repository__title'>"
+ repo.username +
"</div>"
;
if
(repo.realname) {
markup +=
"<div class='select2-result-repository__description'>"
+ repo.realname +
"</div>"
;
}
markup +=
"<div class='select2-result-repository__statistics'>"
+
"<div class='select2-result-repository__forks'><i class='fa fa-user'></i> 下級會員數"
+ repo.children_count +
" </div>"
+
"</div>"
+
"</div></div>"
;
return
markup;
},
templateSelection :
function
(repo) {
return
repo.realname || repo.text;
}
// 列表中選擇某一項后顯示到文本框的內容
});
});
});
</script>
|
第三步、Java端接收參數並返回結果集,不用我強調,這步很重要
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@RequestMapping(value =
"loadMembersInfo"
)
public void loadMembersInfo(HttpServletRequest request, HttpServletResponse response) throws IOException {
Integer uid = StrUtil.parseStringToInt(request.getParameter(
"uid"
));
Members mem =
this
.memberService.selectByPrimaryKey(uid);
// 分頁參數的轉換,需要和前台select2進行匹配,下文放代碼
BaseConditionVO vo = getBaseConditionVOForTable(request);
vo.addParams(
"username"
, StrUtil.getUTF8String(request.getParameter(
"username"
)));
vo.addParams(
"uid"
, uid);
// 封裝結果集,和前台select2也是匹配的。
PageGrid page = createPageGrid(
this
.membersMapper.getPromoterList(vo, vo.createRowBounds()), vo,
this
.membersMapper.searchPromoterTotalCount(vo));
// 以json格式寫入到response
out(page, response);
}
|
接下來,把關鍵的源碼貼出來,可能和你的項目不吻合,但可以參考。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
BaseConditionVO.Java
public class BaseConditionVO {
public final static int PAGE_SHOW_COUNT = 50;
private int pageNum = 1;
private int numPerPage = 0;
private int totalCount = 0;
private String orderField;
private String orderDirection;
/**
* @Fields ps : 對參數類型進行封裝.
*/
private Map<String, Object> mo =
new
HashMap<String, Object>();
public int getPageNum() {
return
pageNum;
}
public void setPageNum(int pageNum) {
this
.pageNum = pageNum;
}
public int getNumPerPage() {
return
numPerPage > 0 ? numPerPage : PAGE_SHOW_COUNT;
}
public void setNumPerPage(int numPerPage) {
this
.numPerPage = numPerPage;
}
public String getOrderField() {
return
orderField;
}
public void setOrderField(String orderField) {
this
.orderField = orderField;
}
public String getOrderDirection() {
return
"desc"
.equals(orderDirection) ?
"desc"
:
"asc"
;
}
public void setOrderDirection(String orderDirection) {
this
.orderDirection = orderDirection;
}
public int getTotalCount() {
return
totalCount;
}
public void setTotalCount(int totalCount) {
this
.totalCount = totalCount;
}
public int getStartIndex() {
int pageNum =
this
.getPageNum() > 0 ?
this
.getPageNum() - 1 : 0;
return
pageNum *
this
.getNumPerPage();
}
public RowBounds createRowBounds() {
RowBounds ro =
new
RowBounds(
this
.getStartIndex(),
this
.getNumPerPage());
return
ro;
}
/**
* @Title: addParams
* @Description: 添加查詢條件
* @param key
* @param value
*/
public void addParams(String key, Object value) {
this
.getMo().put(key, value);
}
/**
* @Title: getParams
* @Description: 獲取查詢條件
* @param key
* @return
*/
public Object getParams(String key) {
return
this
.getMo().get(key);
}
/**
* @return the mo
*/
public Map<String, Object> getMo() {
return
mo;
}
/**
* @param mo
* the mo to set
*/
public void setMo(Map<String, Object> mo) {
this
.mo = mo;
}
}
|
selec2的分頁和Java端分頁參數匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
protected BaseConditionVO getBaseConditionVOForTable(HttpServletRequest req) {
BaseConditionVO vo =
new
BaseConditionVO();
// 當前頁
int currentPage = StrUtil.parseStringToInt(req.getParameter(
"page"
));
// 一頁顯示多少行
int sizes = StrUtil.parseStringToInt(req.getParameter(
"rows"
));
// 排序
String sortOrder = StrUtil.getString(req.getParameter(
"sord"
));
String sortCol = StrUtil.getString(req.getParameter(
"sidx"
));
vo.setNumPerPage(sizes);
vo.setPageNum(currentPage);
vo.setOrderField(sortCol);
vo.setOrderDirection(sortOrder);
return
vo;
}
|
Java端到select2端的數據封裝
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
@XStreamAlias(
"pageGrid"
)
@SuppressWarnings(
"rawtypes"
)
public class PageGrid {
private int page;
// 總頁數,和select2的processResults.pagination匹配
private int total;
private int records;
// 數據結果集,和select2的processResults.results匹配
private List data;
public int getPage() {
return
this
.page;
}
public void setPage(int page) {
this
.page = page;
}
public int getTotal() {
return
this
.total;
}
public void setTotal(int total) {
this
.total = total;
}
public int getRecords() {
return
this
.records;
}
public void setRecords(int records) {
this
.records = records;
}
public List getData() {
return
this
.data;
}
public void setData(List data) {
this
.data = data;
}
}
|
MySQL獲取的數據源和PageGrid進行轉換匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
protected PageGrid createPageGrid(List list, BaseConditionVO vo, int searchTotalCount) {
PageGrid pageGrid =
new
PageGrid();
// 數據
pageGrid.setData(list);
// 當前頁
pageGrid.setPage(vo.getPageNum());
// 總數目
pageGrid.setRecords(list.size());
// 總頁數
int total = 0;
if
(pageGrid.getRecords() != 0) {
total = searchTotalCount % vo.getNumPerPage() == 0 ? searchTotalCount / vo.getNumPerPage()
: searchTotalCount / vo.getNumPerPage() + 1;
}
pageGrid.setTotal(total);
return
pageGrid;
}
|
mybatis的分頁,超簡單,只要設置了createRowBounds,mybatis就會自動為你分頁,這個就厲害了。
1
|
List getPromoterList(BaseConditionVO vo, RowBounds createRowBounds);
|
sql語句,這里的關鍵點是必須要回傳id(m.uid as id)到select2.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<select id=
"getPromoterList"
resultType=
"hashmap"
parameterType=
"map"
>
select
m.uid as id,
convert(m.username,char) username,
m.realname,
m.children_count,
m.headimgUrl
from
members m
where m.deleteflag=0
<
if
test=
"mo.username != ''"
>and m.username like CONCAT(
'%'
,
'${mo.username}'
,
'%'
)</
if
>
<choose>
<when test=
"orderField !=null and orderField !=''"
>
ORDER BY ${orderField}
<
if
test=
"orderDirection != null and orderDirection != ''"
>${orderDirection}</
if
>
</when>
<otherwise>
order by m.username DESC
</otherwise>
</choose>
</select>
|
你是不是沒看見mysql的分頁limit,嗯,這里無須關注,這就是框架要為我們做的事情。
總數
1
|
int searchPromoterTotalCount(BaseConditionVO vo);
|
count(0)就好
1
2
3
4
5
6
7
|
<select id=
"searchPromoterTotalCount"
resultType=
"java.lang.Integer"
parameterType=
"map"
>
select count(0) as a
from
members m
where m.deleteflag=0
<
if
test=
"mo.username != ''"
>and m.username like CONCAT(
'%'
,
'${mo.username}'
,
'%'
)</
if
>
</select>
|
out輸出到response中
1
2
3
4
5
6
|
protected void out(Object result, HttpServletResponse response) throws IOException {
ServletOutputStream out = response.getOutputStream();
ObjectMapper objectMapper =
new
ObjectMapper();
objectMapper.writeValue(out, result);
out.flush();
}
|
到這,select2的remote功能在代碼部分就完全貼出來完了。
不過,我最后還是要強調幾個點:
1.分頁的參數Java端和select2一定要對照起來。
2.回傳的數據一定要傳遞一個id回來,否則回來的列表不能選中,為什么呢?調查select2的源碼可以知道。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
Results.prototype.option =
function
(data) {
var
option = document.createElement(
'li'
);
option.className =
'select2-results__option'
;
var
attrs = {
'role'
:
'treeitem'
,
'aria-selected'
:
'false'
};
if
(data.disabled) {
delete
attrs[
'aria-selected'
];
attrs[
'aria-disabled'
] =
'true'
;
}
// id為空的情況下,刪除的aria-selected,而aria-selected恰好又是列表選中的關鍵屬性。
// 這個就是個坑,只能這么說,select2給出的api上完全不講這點,我去!!!!!!!
if
(data.id ==
null
) {
delete
attrs[
'aria-selected'
];
}
......
}
|
3.form表單如何獲取select2的值?答案是,1.返回結果集必須有id,2.input標簽上必須要name屬性。
4.如何自定義inputMessage呢?
在select2.js中找到以下代碼,注意注釋部分
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
S2.define(
'select2/data/minimumInputLength'
,[
],
function
() {
function
MinimumInputLength (decorated, $e, options) {
this
.minimumInputLength = options.get(
'minimumInputLength'
);
// inputMessage
this
.inputMessage = options.get(
'inputMessage'
);
decorated.call(
this
, $e, options);
}
MinimumInputLength.prototype.query =
function
(decorated, params, callback) {
params.term = params.term ||
''
;
if
(params.term.length <
this
.minimumInputLength) {
this
.trigger(
'results:message'
, {
message:
'inputTooShort'
,
args: {
minimum:
this
.minimumInputLength,
input: params.term,
inputMessage :
this
.inputMessage,
// inputMessage,傳遞給i18n
params: params
}
});
return
;
}
decorated.call(
this
, params, callback);
};
return
MinimumInputLength;
});
|
select2.js中defaults中增加上inputMessage
1
2
3
4
5
6
7
|
this
.defaults = {
...
minimumInputLength: 0,
inputMessage:
''
,
maximumInputLength: 0,
...
};
|
然后在zh-CN.js文件中修改inputTooShort方法
1
2
3
4
5
6
7
8
|
inputTooShort :
function
(e) {
if
(e.inputMessage) {
return
e.inputMessage;
// 增加inputMessage
}
else
{
var
t = e.minimum - e.input.length, n =
"請再輸入至少"
+ t +
"個字符"
;
return
n
}
},
|
原文鏈接:http://blog.csdn.net/qing_gee/article/details/72519313