select2插件很好用,但是樣式在其基礎上改了又改都覺得不好。。。於是選擇只使用它的展示框,而不使用它的下拉框,自己寫一個列表來配合使用,下圖為修改后的樣子:
選擇的樣子:
限制選擇個數的樣子:
下面說說思路:
1、使用 $(".select").on("select2:opening", function (e) {return false;}) 來阻止下拉框的彈出事件。
2、然后我們自己寫一個列表,這里我用的是 angular ,直接 repeat 出來的列表,高效好用。
3、展示框只有取消選中操作,所以通過 unselect 事件來監聽它的值的改變。
4、列表綁定點擊事件,通過判斷當前節點的選中與否,進行選中取消選中。
5、取消選中這里需要注意一下,因為貌似 select2 沒有相關取消一個節點選中的 api ,所以這個實現的思路就是選中的數組中移除要取消的選中項,然后將剩余項重新設置選中。
接着是萬眾期待的環節:
引入依賴文件
<script src='angular.js'></script> <script src='jquery-1.11.3.js'></script> <script src="select2.js"></script> <link rel="stylesheet" href="select2.css">
自己做的樣式:
<style> div.selectList { width: 50%; margin: auto; } div.selectList ul { list-style: none; padding: 0px; } div.selectList li { display: inline-block; margin: 3px; padding:3px 5px; background-color: #ddd; border: 1px solid #aaa; border-radius: 4px; } div.selectList a { cursor: pointer; } div.selectList .selected { background: #63a855; border: #63a800 solid 1px; color: #fff; } div.selectList a:hover { text-decoration: underline; } .box { text-align: center; margin-top:30px; } .box .select2-container--default .select2-selection--multiple .select2-selection__choice { background-color: #fff; border: 1px solid #aaa; } .box .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { color: #fff; border: 1px solid #ccc; background: #ccc; border-radius: 9px; float: right; font-size: 12px; margin-left: 4px; margin-top: 1px; } .box .select2-container--default .select2-results__option[aria-selected=true] { background-color: #eee; } .box .select2-container--default .select2-selection--multiple .select2-selection__clear { position: absolute; display: inline-block; right: 0; margin: 0; } <style>
創建的指令:
.directive('multipleSelectInput', function ($parse) { return { restrict: 'EA', template: "<div class='box'><select style='width: 50%' id='selectInput'></select></div>" + "<div class='selectList'><ul>" + "<li ng-repeat='obj in showList' ng-class='" + '{"selected"' + ":isSelected(obj)}'>" + '<a ng-click="changeSelect(obj)">{{obj.text}}</a>' + '<input type="checkbox" ng-click="changeSelect(obj)" ng-checked="obj.selected" ng-disabled="!obj.selected && !canNotSelected">' + "</li></ul></div>", scope: { selectedList: '=', maxNodes: '=' }, link: function ($scope, elem, attrs, ngModel) { attrs.$observe('multipleSelectInput', function (key) { // console.log(key); if (key.length != 0) { start(key); } }); function start(data) { //下方展示擴展詞列表 $scope.showList = angular.fromJson(data); //存儲選中的節點數組 $scope.selectedList = []; //checkbox 是否能選擇 $scope.canNotSelected = true; //目標元素 var $eventSelect = $("#selectInput"); //初始化 $eventSelect.select2({ data: angular.fromJson(data), placeholder: '請選擇', allowClear: true, multiple: true }); //禁掉下拉框打開,自帶效果與需求不符,自己寫列表 $eventSelect.on("select2:opening", function (e) { console.log('open'); return false;}); //監聽取消選中 $eventSelect.on("select2:unselect", function (e) { $scope.$apply(function() { $scope.getSelected(); //刪除選中節點的信息 var data = e.params.data; // console.log(data); angular.forEach( $scope.showList, function (obj) { if(obj.id == data.id) { obj.selected = false; } }) }) }); $scope.isSelected = function(obj) { if(obj.selected) { return true; } return false; }; $scope.changeSelect = function (obj) { //預先判斷,如果臨近最大限制,那么此次執行點擊選中后會到大限制,那么將其余項的 checkbox 置 disabled if(!obj.selected && $scope.selectedList.length >= $scope.maxNodes - 1) { $scope.canNotSelected = false; } else { $scope.canNotSelected = true; } //判斷限制最大個數 if(!obj.selected && $scope.selectedList.length >= $scope.maxNodes) { console.log('max length : ' + $scope.maxNodes); return; } if(obj.selected) { obj.selected = false; //取消選中,從數組中移除對應節點 // console.log($scope.selectedList); angular.forEach($scope.selectedList, function (data, i) { if(obj.id == data.id) { $scope.selectedList.splice(i, 1); $scope.inputSelectedFnc($scope.selectedList); return; } }); } else { obj.selected = true; //選中則壓入數組進行設置選中 $scope.selectedList.push(obj); $scope.inputSelectedFnc($scope.selectedList); } }; // 設置選中 $scope.inputSelectedFnc = function (arr) { var initSelectArr = []; for(var i = 0; i < arr.length; i ++) { initSelectArr.push(arr[i].id); } $eventSelect.val(initSelectArr).trigger('change'); }; //初始化選中項 //$scope.inputSelectedFnc(angular.fromJson(data)); //獲取選中項 $scope.getSelected = function () { $scope.selectedList = $eventSelect.select2("data"); // console.log($scope.selectedList); } } } } })
數據結構:
id 是不能重復的,text 是文本信息,selected 為列表判斷是否選中標記,其余不重要。
$scope.list = [ { id: 0, text: 'red red red', color: 'red', selected: false}, { id: 1, text: 'blue blue blue', color: 'blue', selected: false}, { id: 2, text: 'yellow yellow yellow', color: 'yellow', selected: false}, { id: 3, text: 'black black black', color: 'black', selected: false}, { id: 4, text: 'purple purple purple', color: 'purple', selected: false}, { id: 5, text: 'white white white', color: 'white', selected: false}, { id: 6, text: 'gray gray gray', color: 'gray', selected: false}, { id: 7, text: 'brown brown brown', color: 'brown', selected: false}, { id: 8, text: 'green green green', color: 'green', selected: false}, { id: 9, text: 'orange orange orange', color: 'orange', selected: false}, { id: 10, text: 'red red red', color: 'red', selected: false}, { id: 11, text: 'blue blue blue', color: 'blue', selected: false}, { id: 12, text: 'yellow yellow yellow', color: 'yellow', selected: false}, { id: 13, text: 'black black black', color: 'black', selected: false}, { id: 14, text: 'purple purple purple', color: 'purple', selected: false}, { id: 15, text: 'white white white', color: 'white', selected: false}, { id: 16, text: 'gray gray gray', color: 'gray', selected: false}, { id: 17, text: 'brown brown brown', color: 'brown', selected: false}, { id: 18, text: 'green green green', color: 'green', selected: false}, { id: 19, text: 'orange orange orange', color: 'orange', selected: false} ];
指令調用方法:
<div multiple-select-input="{{list}}" selected-list="selectedList" max-nodes='3'></div>
獲取選中數據方法:
<button ng-click="get(selectedList)">get information</button> <script> $scope.get = function (data) { console.log(data); } </script>