二、导入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