Commit 7ec0b5330b4893d32d949532b1ad02c506c05e4e

Authored by 梁灏
1 parent 7959adf7

Cascader support search

examples/routers/cascader.vue
... ... @@ -2,8 +2,9 @@
2 2 <Row>
3 3 <i-col span="4">
4 4 <Button @click="handleLoad">load</Button>
  5 + {{ v1 }}
5 6 </i-col>
6   - <i-col span="6">
  7 + <i-col span="4">
7 8 <Cascader :data="data3" filterable v-model="v1"></Cascader>
8 9 <!--<Cascader :data="data2" filterable v-model="v1" :loadData="loadData"></Cascader>-->
9 10 </i-col>
... ... @@ -14,23 +15,26 @@
14 15 data () {
15 16 return {
16 17 v1: [],
17   - data2: [{
18   - value: 'zhejiang',
19   - label: '浙江',
20   - children: [],
21   - loading: false
22   - }, {
23   - value: 'jiangsu',
24   - label: '江苏',
25   - children: [{
26   - value: 'nanjing',
27   - label: '南京',
  18 + data2: [
  19 + {
  20 + value: 'zhejiang',
  21 + label: '浙江',
  22 + children: [],
  23 + loading: false
  24 + },
  25 + {
  26 + value: 'jiangsu',
  27 + label: '江苏',
28 28 children: [{
29   - value: 'zhonghuamen',
30   - label: '中华门'
  29 + value: 'nanjing',
  30 + label: '南京',
  31 + children: [{
  32 + value: 'zhonghuamen',
  33 + label: '中华门'
  34 + }]
31 35 }]
32   - }]
33   - }],
  36 + }
  37 + ],
34 38 data3: [{
35 39 value: 'beijing',
36 40 label: '北京',
... ... @@ -67,6 +71,7 @@
67 71 label: '苏州',
68 72 children: [
69 73 {
  74 + disabled: true,
70 75 value: 'zhuozhengyuan',
71 76 label: '拙政园',
72 77 },
... ...
src/components/cascader/cascader.vue
... ... @@ -5,7 +5,8 @@
5 5 <i-input
6 6 :readonly="!filterable"
7 7 :disabled="disabled"
8   - v-model="displayRender"
  8 + :value="displayRender"
  9 + @on-change="handleInput"
9 10 :size="size"
10 11 :placeholder="placeholder"></i-input>
11 12 <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon>
... ... @@ -16,12 +17,23 @@
16 17 <Drop v-show="visible">
17 18 <div>
18 19 <Caspanel
  20 + v-show="!filterable || (filterable && query === '')"
19 21 ref="caspanel"
20 22 :prefix-cls="prefixCls"
21 23 :data="data"
22 24 :disabled="disabled"
23 25 :change-on-select="changeOnSelect"
24 26 :trigger="trigger"></Caspanel>
  27 + <div :class="[prefixCls + '-dropdown']" v-show="filterable && query !== ''">
  28 + <ul :class="[selectPrefixCls + '-dropdown-list']">
  29 + <li
  30 + :class="[selectPrefixCls + '-item', {
  31 + [selectPrefixCls + '-item-disabled']: item.disabled
  32 + }]"
  33 + v-for="(item, index) in querySelections"
  34 + @click="handleSelectItem(index)">{{ item.label }}</li>
  35 + </ul>
  36 + </div>
25 37 </div>
26 38 </Drop>
27 39 </transition>
... ... @@ -37,6 +49,7 @@
37 49 import Emitter from '../../mixins/emitter';
38 50  
39 51 const prefixCls = 'ivu-cascader';
  52 + const selectPrefixCls = 'ivu-select';
40 53  
41 54 export default {
42 55 name: 'Cascader',
... ... @@ -100,11 +113,13 @@
100 113 data () {
101 114 return {
102 115 prefixCls: prefixCls,
  116 + selectPrefixCls: selectPrefixCls,
103 117 visible: false,
104 118 selected: [],
105 119 tmpSelected: [],
106 120 updatingValue: false, // to fix set value in changeOnSelect type
107   - currentValue: this.value
  121 + currentValue: this.value,
  122 + query: ''
108 123 };
109 124 },
110 125 computed: {
... ... @@ -128,6 +143,32 @@
128 143 }
129 144  
130 145 return this.renderFormat(label, this.selected);
  146 + },
  147 + querySelections () {
  148 + let selections = [];
  149 + function getSelections (arr, label, value) {
  150 + for (let i = 0; i < arr.length; i++) {
  151 + let item = arr[i];
  152 + item.__label = label ? label + ' / ' + item.label : item.label;
  153 + item.__value = value ? value + ',' + item.value : item.value;
  154 +
  155 + if (item.children && item.children.length) {
  156 + getSelections(item.children, item.__label, item.__value);
  157 + delete item.__label;
  158 + delete item.__value;
  159 + } else {
  160 + selections.push({
  161 + label: item.__label,
  162 + value: item.__value,
  163 + item: item,
  164 + disabled: !!item.disabled
  165 + });
  166 + }
  167 + }
  168 + }
  169 + getSelections(this.data);
  170 + selections = selections.filter(item => item.label.indexOf(this.query) > -1);
  171 + return selections;
131 172 }
132 173 },
133 174 methods: {
... ... @@ -146,7 +187,7 @@
146 187 toggleOpen () {
147 188 if (this.disabled) return false;
148 189 if (this.visible) {
149   - this.handleClose();
  190 + if (!this.filterable) this.handleClose();
150 191 } else {
151 192 this.onFocus();
152 193 }
... ... @@ -177,6 +218,19 @@
177 218 });
178 219 });
179 220 }
  221 + },
  222 + handleInput (event) {
  223 + this.query = event.target.value;
  224 + },
  225 + handleSelectItem (index) {
  226 + const item = this.querySelections[index];
  227 +
  228 + if (item.item.disabled) return false;
  229 + this.query = '';
  230 + const oldVal = JSON.stringify(this.currentValue);
  231 + this.currentValue = item.value.split(',');
  232 + this.emitValue(this.currentValue, oldVal);
  233 + this.handleClose();
180 234 }
181 235 },
182 236 created () {
... ...
src/styles/components/cascader.less
... ... @@ -49,6 +49,10 @@
49 49  
50 50 .select-item(@cascader-prefix-cls, @cascader-item-prefix-cls);
51 51  
  52 + &-dropdown{
  53 + padding: 5px 0;
  54 + }
  55 +
52 56 &-menu{
53 57 display: inline-block;
54 58 min-width: 100px;
... ...