Select2的使用

Select2的使用

Select2是一款基于JQuery的下拉列表插件,主要用来优化select,支持单选和多选,同时也支持分组显示、列表检索、远程获取数据等众多好用的功能

项目地址:https://select2.org/

基本使用

需要用到的JS和CSS文件位于项目代码下的dist目录中,需要将这个目录中的对应文件放入你的项目里,这一步不赘述

  1. 引入CSS/JS文件,由于Select2是基于Jquery的,所以要先引入Jquery,这里我们都直接引入CDN的地址
<!-- 加载 Jquery -->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>

<!-- 加载 Select2 -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/css/select2.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.8/js/select2.min.js"></script>
  1. 初始化Select2
<select class="form-control" id="id_select2_demo1">
    <option value="">-----单选-----</option>
    <option value="1">OPS-COFFEE-A</option>
    <option value="2">OPS-COFFEE-B</option>
    <option value="3">OPS-COFFEE-C</option>
    <option value="4">OPS-COFFEE-D</option>
    <option value="5">OPS-COFFEE-E</option>
    <option value="6">OPS-COFFEE-F</option>
    <option value="7">OPS-COFFEE-G</option>
</select>

<script>
    var selectorx = $('#id_select2_demo1').select2();
</script>
  1. 完成以上两步可以看到页面效果如下

img

设置提示语placeholder

$('#id_select2_demo1').select2({
    placeholder: '请选择'
});

placeholder: 选择框的提示语,需要注意,要想让这个提示语生效,需要select的option里边有一个value为空的option,例如上边例子中的

<option value="">-----单选-----</option>

隐藏搜索框

与默认的select除了样式上的区别外,最重要的是多了个搜索框,能用来搜索option项,如果你不想显示这个搜索框,可以通过设置项minimumResultsForSearch隐藏

var selectorx = $('#id_select2_demo1').select2({
    minimumResultsForSearch: -1
});

加载本地数据

除了实例化已经存在的select之外,也可以通过设置项data加载本地数据

var sdata = [
    {id: 1, text:'OPS-COFFEE-1'},
    {id: 2, text:'OPS-COFFEE-2'},
    {id: 3, text:'OPS-COFFEE-3'}
]

$('#id_select2_demo2').select2({
    data: sdata
});

select2能够加载的数据格式如上,需要两个数据属性idtext,当然你也可以加载其他的额外属性以在需要时获取

加载远程数据

除了加载本地数据外,也支持ajax异步去后端获取数据,用法如下:

$('#id_select2_demo3').select2({
    placeholder: 'Ajax后端获取数据示例',
    ajax: {
      url: "sdata.json",
      dataType: 'json',
      delay: 250,
      data: function (params) {
        return {
          search: params.term,
        };
      },
      processResults: function (data) {
        return {
          results: data
        };
      },
      cache: true
    },
    minimumInputLength: 2
});

delay: 250: 配置告诉select2在用户停止输入多少毫秒后开始查询,合理设置可以避免频繁向后端发送请求

search: params.term: 定义了要传递给后端的查询参数,search为发送到服务端的参数名,params.term表示输入框中输入的内容,当然这里也可以添加一些自定义的参数,例如:

data: function (params) {
    return {
      search: params.term,
      site: "https://ops-coffee.cn"
    };
},

那么当你输入OPS时,服务端接受到的完整参数就是/sdata.json?search=OPS&site=https://ops-coffee.cn

results: data: 定义了后台返回的数据,其中data为select2能够识别的格式,如果后端返回的格式不是select2能够识别的格式,例如下边这样

{
    "state": 1, 
    "message":[
        {"id": 0, "text":"-----单选-----"},
        {"id": 1, "text":"OPS-COFFEE-1"},
        {"id": 2, "text":"OPS-COFFEE-2"},
        {"id": 3, "text":"OPS-COFFEE-3"}
    ]
}

那么你需要先将其处理成select2能够识别的格式,这里我们就需要取出date中的message

processResults: function (data) {
    return {
      results: data.message
    };
},

minimumInputLength: ajax异步请求通常我们会配合配置项minimumInputLength使用,这个配置项的意思是输入指定长度的字符后开始搜索,也就是点击select选择框默认不会去后台请求数据,当你输入指定长度的字符时才会去搜索,这样在你搜索项非常多的时候能更精确的匹配你想要的内容

如果你想点击即显示所有option,那么你可以将他的值设置为0,或者不配置这个配置

同时也可以通过maximumInputLength配置项配置输入字符的最大长度

多选支持

select2对多选的支持也非常简单,跟默认的select标签一样只需要在select标签中添加multiple="multiple"即可

<select class="form-control" id="id_select2_demo4" multiple="multiple">
    <option value="1">OPS-COFFEE-A</option>
    <option value="3">OPS-COFFEE-C</option>
    <option value="4">OPS-COFFEE-D</option>
    <option value="5">OPS-COFFEE-E</option>
</select>

var selectory = $('#id_select2_demo4').select2({
    placeholder: '请选择,最多选择三个',
    allowClear: true,
    maximumSelectionLength:3,
});

显示效果如下:

img

allowClear: 是否显示清楚按钮,默认false,如果设置为true,需要同时配置placeholder,否则可能会引起js报错:

TypeError: Cannot read property 'id' of undefined

maximumSelectionLength: 配置最多能选择多少项

配置说明

另外还有几个配置上边没有讲到的:

width: 宽度,例如100%

multiple: 是否支持多选,默认false

closeOnSelect: 是否选中后关闭选择框,默认true

tags: 是否可以动态创建选项

disabled: 是否禁用

debug: 是否开启debug模式

使用进阶

获取已选择的值,无论是单选还是多选都可以用下边的代码来获取选择的option

$('#id_select2_demo4').select2('val')

获取已选择的对象

$("#id_select2_demo4").select2("data")

如果想要拿到已选择option的text值,可以通过如下方法,以下代码中的[0]用来获取第一个对象,对单选合适,如果是多选的话需要循环获取

$("#id_select2_demo4").select2("data")[0].text

selected,初始化值,设置选中项

# 单选情况下val为数字,这里的selectx为
$("#id_select2_demo1").val(2).trigger("change");

# 多选情况下val为列表
$("#id_select2_demo4").val([2,3,5]).trigger("change");

清空已选择的值,无论是单选还是多选都可以这样清除

$("#id_select2_demo1").val(null).trigger('change');
$("#id_select2_demo4").val(null).trigger('change');

禁用select2

$("#id_select2_demo1").prop('disabled',true);;
$("#id_select2_demo4").prop('disabled',true);;

动态添加select的option

$('#add').click(function() {
    var _html = '<option value="9" selected>ops-coffee.cn</option>';
    $('#id_select2_demo1').append(_html).trigger('change.select2');
    $('#id_select2_demo1').select2("open");
})

change.select2: 新增select数据后触发select2更新

.select2("open"): 打开select,open改为close可动态关闭select,改为destroy可销毁select2,恢复select默认样式

实现下拉框中显示图片

一、固定方式:

html代码:

<body style="margin-left:2%">
    <div>
    <h2><label>固定方式获取</label></h2>
        <p>
            <label>单选:</label>
            <select class="form-control" style="width: 50%" id="sel_1">
                <option value="root">ROOT</option>
                <option value="aojiancc">傲剑</option>
                <option value="huangleicc">黄磊</option>
            </select>
        </p>
        <p>
            <label>分组多选:</label>
            <select class="form-control" style="width: 50%" multiple="multiple" id="sel_2">
                <optgroup label="管理员">
                    <option value="root">ROOT</option>
                </optgroup>
                <optgroup label="用户">
                    <option value="aojiancc">傲剑</option>
                    <option value="huangleicc">黄磊</option>
                </optgroup>
            </select>
        </p>
        <p>
            <label>图文结合:</label>
            <select class="js-example-templating js-states form-control" style="width: 50%" multiple="multiple" id="sel_3">
                <optgroup label="管理员">
                    <option value="root">ROOT</option>
                </optgroup>
                <optgroup label="用户">
                    <option value="aojiancc">傲剑</option>
                    <option value="huangleicc">黄磊</option>
                </optgroup>
            </select>
        </p>
    </div>
</body>

JS代码:

<script>
    //单选
    $(document).ready(function () {
        $('#sel_1').select2();
            
         //设置最多能够选择的个数
         $("#sel_2").select2({
            tags: true,
            placeholder: '请选择',
            maximumSelectionLength: 2 //最多能够选择的个数
         });

         //带图片
         $("#sel_3").select2({
             placeholder: '请选择',
             templateResult: formatStateResult,//选择时
             templateSelection: formatStateSelection//选择后
         });
            
     });
     //填充图片
     function formatStateResult(state) {
         if (!state.id) { return state.text; }
         var $state = $(
             '<span><img src="/img/a5.jpg" style="width: 5%;height:5%" class="img-flag" /> ' + state.text + '</span>'
         );
         return $state;
     };
     function formatStateSelection(state) {
         if (!state.id) { return state.text; }
         var $state = $(
             '<span><img src="/img/a5.jpg" style="width: 10%;height:10%" class="img-flag" /> ' + state.text + '</span>'
         );
         return $state;
     };
</script>

效果:

单选:

img

二、ajax获取方式(以最复杂的分页多选且显示图片为例):

html代码:

<body style="margin-left:2%">
    <div>
        <h2><label>远程方式获取</label></h2>
        <p>
            <label>图文结合:</label>
            <select class="js-example-data-ajax js-states form-control" style="width: 50%" multiple="multiple" id="sel_4">
                <option></option>
            </select>
        </p>
    </div>
</body>

JS代码:

<script>
$(document).ready(function () {
	$("#sel_4").select2({
		ajax: {
			url: '/ExportExcel/GetPageListJson',
			dataType: 'json',
			delay: 1000,// 搜索延迟显示
			//data:参数
			data: function (params) {
				return {
					LikeVar: params.term, // 搜索框值
					page: params.page || 1,//分页,当前页
					rows: 2//每页容量

				};
			},
			//数据集处理
			processResults: function (data, params) {
			    params.page = params.page  || 1;
			    return {
			        //这里是返回的数据:数据格式必须遵循select2格式 如:{ id: 1, text: 'aojian' }, { id: 2, text: 'dahuang' }];
				results: data.rows,
				pagination: {
				    //more:表示下拉刷新,data.total表示总页数,这里的意思是当前页小于总页数的时候就显示下拉分页
				    more: (params.page) < data.total
        			}
			    };
			},
			cache: true
		},
		placeholder: '请选择',//默认文字提示
		language: "zh-CN",//语言
		tags: true,//允许手动添加
		allowClear: true,//允许清空
		escapeMarkup: function (markup) { return markup; }, // 自定义格式化防止xss注入
		minimumInputLength: 1,//输入几个字符后开始查询,1:表示一个字符
		templateResult: formatRepoProvince, //显示的结果集格式,这里需要自己写css样式
		templateSelection: formatRepoProvince //选择某一项后显示到文本框的内容
	});

	//$("#sel_4").trigger('change');//使用append拼接时需重新渲染
});
//编写样式
function formatRepoProvince(repo) {
	console.log(repo);
	if (repo.loading) return repo.text;
	var imgs = repo.img;
	imgs = imgs.substring(1, imgs.length);
	var markup = '<span><img src="' + imgs + '" style="width: 5%;height:5%" class="img-flag"/> ' + repo.text + '</span>';
	return markup;
}
</script>

效果:

img

设置默认值:

$('#sel_4').val(['2']).trigger('change');//其中2是id或者value的值,是list格式。change是固定值

option分页实现

如果option 太多 直接渲染,页面渲染会很慢,这时候就要分页,分页如何实现呢?

文档:https://select2.org/data-sources/ajax

下面是个参考

js

//标签
$('#materiasort2').select2({
	width:'100%',
	//提示语
	placeholder: '请选择标签',
	/*//在用户停止输入250毫秒后开始查询
	delay: 250,
	//输入指定2个字符后开始搜索
	minimumInputLength: 2,*/
	ajax: {
		//请求后端分页数据的url
		url: '{:url("index/material/keywordList")}',
		type: "POST",
		data: function (params) {
			var query = {
				search: params.term,
				page: params.page || 1
			}

			// Query parameters will be ?search=[term]&page=[page]
			return query;
		}
	}
})

后端(php,tp5.1)

//标签分页
public function keywordList(){
	//页码
	$page = input('page');
	//每页条数
	$pageSize = 15;
	$keywordList = KeywordsModel::where('active',1)->limit(($page - 1) * $pageSize, $pageSize)->select();
	//查询是否有下一页
	$nextCount = KeywordsModel::where('active',1)->limit($page * $pageSize, $pageSize)->select()->count();

	//返回格式
	/*
	 *{
		  "results": [
			{
			  "id": 1,
			  "text": "Option 1"
			},
			{
			  "id": 2,
			  "text": "Option 2"
			}
		  ],
		  "pagination": {
			"more": true
		  }
		}
	 *
	 */
	$results = array();
	$pagination = array();

	//遍历数据
	foreach ($keywordList as $keyword){
		 $temp = array();
		 $temp['id'] = $keyword->id;
		 $temp['text'] = $keyword->title;
		 $results[] = $temp;
	}

	//有下一页
	if($nextCount > 0){
		$pagination['more'] = true;
	}else{
		$pagination['more'] = false;
	}
	$data = [
		'results' => $results,
		'pagination' => $pagination,
	];
	return json($data);
}

ajax方式加载数据,编辑数据回显

//标签
var materiasort2SelectNode = $('#materiasort2').select2({
	width:'100%',
	//提示语
	placeholder: '请选择标签',

	ajax: {
		//请求后端分页数据的url
		url: '{:url("index/material/keywordList")}',
		type: "POST",
		data: function (params) {
			var query = {
				search: params.term,
				page: params.page || 1
			}

			// Query parameters will be ?search=[term]&page=[page]
			return query;
		}
	}
})

function edit(id) {
	$('#modal-edit').modal('toggle');
	$('#edit-id').prop("value", id);
	//注意先清空选中,不然会每点击一次增加一组option
	$('#materiasort2').val(null).trigger('change');
	
	$.ajax({
		url: '{:url("index/material/edit")}',
		type: 'post',
		data: {id: id, action: 1},
		success: function (res) {
			//后端返回的是keywordss 数组
			for(var i = 0; i < res.keywordss.length; i++){
				//这种方式无效
				//keywordssList[keywordssList.length] = res.keywordss[i].id;
			   	/* var option = document.createElement('option');
				option.value = res.keywordss[i].id;
				option.innerText = res.keywordss[i].title;*/
				//这种可以 第一个参数是option中间的文字,第二个是value 第三个位是否默认选中  第四个是否选中
				var option = new Option(res.keywordss[i].title, res.keywordss[i].id, true, true);
				//materiasort2SelectNode 为select2 初始化返回的dom
				materiasort2SelectNode.append(option);
			}
		   
			materiasort2SelectNode.trigger('change');
			
		}
	});
}

设置下拉框和隐藏下拉框

select2中有一个属性,可以设置下拉位置,所以可以根据这个属性设置下拉框显示位置,隐藏的话可以设置disabled,但是这样输入框额去掉选择就不能用了。所以可以用这种方式将下拉框显示到一个隐藏块中

官方文档:https://select2.org/dropdown

例:

<!--select2 隐藏块-->
<div id="myModal" style="display: none">

</div>


$('#id_select2_edit').select2({
    placeholder: '选择标签',
    //将下拉框放到一个不显示块,屏蔽下拉框
    dropdownParent: $('#myModal'),
})

清除选中触发的事件

select2 所有事件:https://select2.org/programmatic-control/events

//select 2 事件注册 移除选中
$('#id_select2_edit').on("select2:unselect", function (e) {
    //事件对象
    console.log(e,11111111111111111);
    //select 参数
    console.log(e.params.data,22222222222);
})

参考:

select2 所有事件:

https://select2.org/programmatic-control/events

https://blog.csdn.net/jiangeeq/article/details/52457351

https://blog.csdn.net/jiangeeq/article/details/52457351

https://ops-coffee.cn/s/2w956ln2fA1jzdC-UQ55Vg

https://www.tnblog.net/18896101294/article/details/2395

posted @ 2020-07-03 11:42  makalo  阅读(4974)  评论(0编辑  收藏  举报