Blame view

src/components/cascader/cascader.vue 11.8 KB
0a48ac45   梁灏   Input add readonl...
1
  <template>
c463ab87   梁灏   add Cascader
2
      <div :class="classes" v-clickoutside="handleClose">
75e5c6a5   梁灏   Cascader support ...
3
4
5
          <div :class="[prefixCls + '-rel']" @click="toggleOpen">
              <slot>
                  <i-input
3ae11e85   梁灏   update Cascader
6
                      ref="input"
5a9a12cd   梁灏   update Cascader
7
                      :readonly="!filterable"
75e5c6a5   梁灏   Cascader support ...
8
                      :disabled="disabled"
3ae11e85   梁灏   update Cascader
9
                      :value="displayInputRender"
7ec0b533   梁灏   Cascader support ...
10
                      @on-change="handleInput"
75e5c6a5   梁灏   Cascader support ...
11
                      :size="size"
3ae11e85   梁灏   update Cascader
12
13
14
15
16
                      :placeholder="inputPlaceholder"></i-input>
                  <div
                      :class="[prefixCls + '-label']"
                      v-show="filterable && query === ''"
                      @click="handleFocus">{{ displayRender }}</div>
47a7f21d   梁灏   support Cascader
17
                  <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSelect"></Icon>
75e5c6a5   梁灏   Cascader support ...
18
19
20
                  <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']"></Icon>
              </slot>
          </div>
47a7f21d   梁灏   support Cascader
21
22
23
24
          <transition name="slide-up">
              <Drop v-show="visible">
                  <div>
                      <Caspanel
7ec0b533   梁灏   Cascader support ...
25
                          v-show="!filterable || (filterable && query === '')"
47a7f21d   梁灏   support Cascader
26
27
28
29
30
31
                          ref="caspanel"
                          :prefix-cls="prefixCls"
                          :data="data"
                          :disabled="disabled"
                          :change-on-select="changeOnSelect"
                          :trigger="trigger"></Caspanel>
7ec0b533   梁灏   Cascader support ...
32
33
34
35
36
37
38
39
40
41
                      <div :class="[prefixCls + '-dropdown']" v-show="filterable && query !== ''">
                          <ul :class="[selectPrefixCls + '-dropdown-list']">
                              <li
                                  :class="[selectPrefixCls + '-item', {
                                      [selectPrefixCls + '-item-disabled']: item.disabled
                                  }]"
                                  v-for="(item, index) in querySelections"
                                  @click="handleSelectItem(index)">{{ item.label }}</li>
                          </ul>
                      </div>
47a7f21d   梁灏   support Cascader
42
43
44
                  </div>
              </Drop>
          </transition>
6ff31952   梁灏   optimize Input sh...
45
      </div>
0a48ac45   梁灏   Input add readonl...
46
47
  </template>
  <script>
6ff31952   梁灏   optimize Input sh...
48
      import iInput from '../input/input.vue';
47a7f21d   梁灏   support Cascader
49
      import Drop from '../select/dropdown.vue';
c463ab87   梁灏   add Cascader
50
51
      import Icon from '../icon/icon.vue';
      import Caspanel from './caspanel.vue';
6ff31952   梁灏   optimize Input sh...
52
      import clickoutside from '../../directives/clickoutside';
c463ab87   梁灏   add Cascader
53
      import { oneOf } from '../../utils/assist';
47a7f21d   梁灏   support Cascader
54
      import Emitter from '../../mixins/emitter';
3ae11e85   梁灏   update Cascader
55
      import Locale from '../../mixins/locale';
6ff31952   梁灏   optimize Input sh...
56
57
  
      const prefixCls = 'ivu-cascader';
7ec0b533   梁灏   Cascader support ...
58
      const selectPrefixCls = 'ivu-select';
6ff31952   梁灏   optimize Input sh...
59
  
0a48ac45   梁灏   Input add readonl...
60
      export default {
34ee7b4a   梁灏   support Tree & ad...
61
          name: 'Cascader',
3ae11e85   梁灏   update Cascader
62
          mixins: [ Emitter, Locale ],
47a7f21d   梁灏   support Cascader
63
          components: { iInput, Drop, Icon, Caspanel },
c463ab87   梁灏   add Cascader
64
          directives: { clickoutside },
0a48ac45   梁灏   Input add readonl...
65
          props: {
6ff31952   梁灏   optimize Input sh...
66
67
68
              data: {
                  type: Array,
                  default () {
b0893113   jingsam   :art: add eslint
69
                      return [];
6ff31952   梁灏   optimize Input sh...
70
71
72
                  }
              },
              value: {
9ec927b1   梁灏   update Cascader
73
74
                  type: Array,
                  default () {
b0893113   jingsam   :art: add eslint
75
                      return [];
9ec927b1   梁灏   update Cascader
76
                  }
6ff31952   梁灏   optimize Input sh...
77
78
79
80
81
82
83
              },
              disabled: {
                  type: Boolean,
                  default: false
              },
              clearable: {
                  type: Boolean,
c463ab87   梁灏   add Cascader
84
                  default: true
6ff31952   梁灏   optimize Input sh...
85
86
              },
              placeholder: {
3ae11e85   梁灏   update Cascader
87
                  type: String
6ff31952   梁灏   optimize Input sh...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
              },
              size: {
                  validator (value) {
                      return oneOf(value, ['small', 'large']);
                  }
              },
              trigger: {
                  validator (value) {
                      return oneOf(value, ['click', 'hover']);
                  },
                  default: 'click'
              },
              changeOnSelect: {
                  type: Boolean,
                  default: false
              },
              renderFormat: {
                  type: Function,
05b5dd7b   梁灏   update Cascader
106
                  default (label) {
bd4e3b9b   梁灏   update Cascader
107
                      return label.join(' / ');
6ff31952   梁灏   optimize Input sh...
108
                  }
f7ffdac5   梁灏   Cascader support ...
109
110
111
              },
              loadData: {
                  type: Function
5a9a12cd   梁灏   update Cascader
112
113
114
115
              },
              filterable: {
                  type: Boolean,
                  default: false
6ff31952   梁灏   optimize Input sh...
116
              }
0a48ac45   梁灏   Input add readonl...
117
118
119
          },
          data () {
              return {
6ff31952   梁灏   optimize Input sh...
120
                  prefixCls: prefixCls,
7ec0b533   梁灏   Cascader support ...
121
                  selectPrefixCls: selectPrefixCls,
c463ab87   梁灏   add Cascader
122
123
                  visible: false,
                  selected: [],
2810d8c7   梁灏   fixed #183
124
                  tmpSelected: [],
47a7f21d   梁灏   support Cascader
125
                  updatingValue: false,    // to fix set value in changeOnSelect type
7ec0b533   梁灏   Cascader support ...
126
127
                  currentValue: this.value,
                  query: ''
b0893113   jingsam   :art: add eslint
128
              };
0a48ac45   梁灏   Input add readonl...
129
130
          },
          computed: {
c463ab87   梁灏   add Cascader
131
132
133
134
              classes () {
                  return [
                      `${prefixCls}`,
                      {
165bb7c9   梁灏   update Cascader
135
                          [`${prefixCls}-show-clear`]: this.showCloseIcon,
3ae11e85   梁灏   update Cascader
136
                          [`${prefixCls}-size-${this.size}`]: !!this.size,
05b5dd7b   梁灏   update Cascader
137
138
                          [`${prefixCls}-visible`]: this.visible,
                          [`${prefixCls}-disabled`]: this.disabled
c463ab87   梁灏   add Cascader
139
                      }
b0893113   jingsam   :art: add eslint
140
                  ];
c463ab87   梁灏   add Cascader
141
142
              },
              showCloseIcon () {
65b41a2d   梁灏   fixed #635
143
                  return this.currentValue && this.currentValue.length && this.clearable && !this.disabled;
c463ab87   梁灏   add Cascader
144
              },
6ff31952   梁灏   optimize Input sh...
145
146
147
148
149
150
              displayRender () {
                  let label = [];
                  for (let i = 0; i < this.selected.length; i++) {
                      label.push(this.selected[i].label);
                  }
  
165bb7c9   梁灏   update Cascader
151
                  return this.renderFormat(label, this.selected);
7ec0b533   梁灏   Cascader support ...
152
              },
3ae11e85   梁灏   update Cascader
153
154
155
156
157
158
159
160
161
162
163
164
165
              displayInputRender () {
                  return this.filterable ? '' : this.displayRender;
              },
              localePlaceholder () {
                  if (this.placeholder === undefined) {
                      return this.t('i.select.placeholder');
                  } else {
                      return this.placeholder;
                  }
              },
              inputPlaceholder () {
                  return this.filterable && this.currentValue.length ? null : this.localePlaceholder;
              },
7ec0b533   梁灏   Cascader support ...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
              querySelections () {
                  let selections = [];
                  function getSelections (arr, label, value) {
                      for (let i = 0; i < arr.length; i++) {
                          let item = arr[i];
                          item.__label = label ? label + ' / ' + item.label : item.label;
                          item.__value = value ? value + ',' + item.value : item.value;
  
                          if (item.children && item.children.length) {
                              getSelections(item.children, item.__label, item.__value);
                              delete item.__label;
                              delete item.__value;
                          } else {
                              selections.push({
                                  label: item.__label,
                                  value: item.__value,
                                  item: item,
                                  disabled: !!item.disabled
                              });
                          }
                      }
                  }
                  getSelections(this.data);
                  selections = selections.filter(item => item.label.indexOf(this.query) > -1);
                  return selections;
6ff31952   梁灏   optimize Input sh...
191
              }
0a48ac45   梁灏   Input add readonl...
192
193
          },
          methods: {
c463ab87   梁灏   add Cascader
194
              clearSelect () {
65b41a2d   梁灏   fixed #635
195
                  if (this.disabled) return false;
47a7f21d   梁灏   support Cascader
196
197
                  const oldVal = JSON.stringify(this.currentValue);
                  this.currentValue = this.selected = this.tmpSelected = [];
165bb7c9   梁灏   update Cascader
198
                  this.handleClose();
47a7f21d   梁灏   support Cascader
199
200
201
                  this.emitValue(this.currentValue, oldVal);
  //                this.$broadcast('on-clear');
                  this.broadcast('Caspanel', 'on-clear');
c463ab87   梁灏   add Cascader
202
203
204
205
              },
              handleClose () {
                  this.visible = false;
              },
75e5c6a5   梁灏   Cascader support ...
206
              toggleOpen () {
2aa0aa6e   Rijn   fix bug: cascader...
207
                  if (this.disabled) return false;
75e5c6a5   梁灏   Cascader support ...
208
                  if (this.visible) {
7ec0b533   梁灏   Cascader support ...
209
                      if (!this.filterable) this.handleClose();
75e5c6a5   梁灏   Cascader support ...
210
211
212
213
                  } else {
                      this.onFocus();
                  }
              },
c463ab87   梁灏   add Cascader
214
215
              onFocus () {
                  this.visible = true;
47a7f21d   梁灏   support Cascader
216
217
                  if (!this.currentValue.length) {
                      this.broadcast('Caspanel', 'on-clear');
165bb7c9   梁灏   update Cascader
218
                  }
c463ab87   梁灏   add Cascader
219
220
              },
              updateResult (result) {
bd4e3b9b   梁灏   update Cascader
221
222
                  this.tmpSelected = result;
              },
165bb7c9   梁灏   update Cascader
223
224
              updateSelected (init = false) {
                  if (!this.changeOnSelect || init) {
47a7f21d   梁灏   support Cascader
225
226
227
                      this.broadcast('Caspanel', 'on-find-selected', {
                          value: this.currentValue
                      });
165bb7c9   梁灏   update Cascader
228
229
230
231
                  }
              },
              emitValue (val, oldVal) {
                  if (JSON.stringify(val) !== oldVal) {
47a7f21d   梁灏   support Cascader
232
                      this.$emit('on-change', this.currentValue, JSON.parse(JSON.stringify(this.selected)));
cc419499   梁灏   fixed #525
233
234
235
236
237
                      this.$nextTick(() => {
                          this.dispatch('FormItem', 'on-form-change', {
                              value: this.currentValue,
                              selected: JSON.parse(JSON.stringify(this.selected))
                          });
cd78c9c4   梁灏   some comps suppor...
238
                      });
165bb7c9   梁灏   update Cascader
239
                  }
7ec0b533   梁灏   Cascader support ...
240
241
242
243
244
245
246
247
              },
              handleInput (event) {
                  this.query = event.target.value;
              },
              handleSelectItem (index) {
                  const item = this.querySelections[index];
  
                  if (item.item.disabled) return false;
3ae11e85   梁灏   update Cascader
248
                  // todo 还有bug,选完,删除后,失焦,不能回到上次选择的
7ec0b533   梁灏   Cascader support ...
249
                  this.query = '';
3ae11e85   梁灏   update Cascader
250
                  this.$refs.input.currentValue = '';
7ec0b533   梁灏   Cascader support ...
251
252
253
254
                  const oldVal = JSON.stringify(this.currentValue);
                  this.currentValue = item.value.split(',');
                  this.emitValue(this.currentValue, oldVal);
                  this.handleClose();
3ae11e85   梁灏   update Cascader
255
256
257
              },
              handleFocus () {
                  this.$refs.input.focus();
c463ab87   梁灏   add Cascader
258
259
              }
          },
687c4562   梁灏   fixed #810
260
          created () {
47a7f21d   梁灏   support Cascader
261
262
263
264
265
266
267
              this.$on('on-result-change', (params) => {
                  // lastValue: is click the final val
                  // fromInit: is this emit from update value
                  const lastValue = params.lastValue;
                  const changeOnSelect = params.changeOnSelect;
                  const fromInit = params.fromInit;
  
bd4e3b9b   梁灏   update Cascader
268
                  if (lastValue || changeOnSelect) {
47a7f21d   梁灏   support Cascader
269
                      const oldVal = JSON.stringify(this.currentValue);
bd4e3b9b   梁灏   update Cascader
270
271
272
273
274
275
                      this.selected = this.tmpSelected;
  
                      let newVal = [];
                      this.selected.forEach((item) => {
                          newVal.push(item.value);
                      });
c463ab87   梁灏   add Cascader
276
  
165bb7c9   梁灏   update Cascader
277
                      if (!fromInit) {
2810d8c7   梁灏   fixed #183
278
                          this.updatingValue = true;
47a7f21d   梁灏   support Cascader
279
280
                          this.currentValue = newVal;
                          this.emitValue(this.currentValue, oldVal);
bd4e3b9b   梁灏   update Cascader
281
282
283
284
285
                      }
                  }
                  if (lastValue && !fromInit) {
                      this.handleClose();
                  }
47a7f21d   梁灏   support Cascader
286
              });
bd4e3b9b   梁灏   update Cascader
287
          },
687c4562   梁灏   fixed #810
288
289
290
          mounted () {
              this.updateSelected(true);
          },
bd4e3b9b   梁灏   update Cascader
291
292
293
          watch: {
              visible (val) {
                  if (val) {
47a7f21d   梁灏   support Cascader
294
                      if (this.currentValue.length) {
bd4e3b9b   梁灏   update Cascader
295
296
                          this.updateSelected();
                      }
3ae11e85   梁灏   update Cascader
297
298
299
300
301
                  } else {
                      if (this.filterable) {
                          this.query = '';
                          this.$refs.input.currentValue = '';
                      }
bd4e3b9b   梁灏   update Cascader
302
                  }
bb1a3c38   梁灏   fixed #593
303
                  this.$emit('on-visible-change', val);
f46ebc38   梁灏   fixed #130
304
              },
47a7f21d   梁灏   support Cascader
305
306
              value (val) {
                  this.currentValue = val;
3bbb6b5f   梁灏   fixed #488
307
                  if (!val.length) this.selected = [];
47a7f21d   梁灏   support Cascader
308
309
310
              },
              currentValue () {
                  this.$emit('input', this.currentValue);
2810d8c7   梁灏   fixed #183
311
312
313
314
315
                  if (this.updatingValue) {
                      this.updatingValue = false;
                      return;
                  }
                  this.updateSelected(true);
48af1359   梁灏   fixed #553
316
              },
f7ffdac5   梁灏   Cascader support ...
317
318
319
320
321
              data: {
                  deep: true,
                  handler () {
                      this.$nextTick(() => this.updateSelected());
                  }
bd4e3b9b   梁灏   update Cascader
322
              }
0a48ac45   梁灏   Input add readonl...
323
          }
b0893113   jingsam   :art: add eslint
324
325
      };
  </script>