Commit 801a9c9d6da5cd275b959dd9c61da376814b0055

Authored by Aresn
Committed by GitHub
2 parents d1038fce 9366c9a7

Merge pull request #3739 from SergioCrisostomo/select-patches

Select improvements for edge cases
src/components/select/select.vue
... ... @@ -82,7 +82,7 @@
82 82 import FunctionalOptions from './functional-options.vue';
83 83  
84 84 const prefixCls = 'ivu-select';
85   - const optionRegexp = /^i-option$|^Option$/;
  85 + const optionRegexp = /^i-option$|^Option$/i;
86 86 const optionGroupRegexp = /option-?group/i;
87 87  
88 88 const findChild = (instance, checkFn) => {
... ... @@ -99,7 +99,7 @@
99 99 const opts = node.componentOptions;
100 100 if (opts && opts.tag.match(optionRegexp)) return [node];
101 101 if (!node.children && (!opts || !opts.children)) return [];
102   - const children = [...(node.children || []), ...(opts && opts.children || [])];
  102 + const children = [...(node.children || []), ...(opts && opts.children || [])];
103 103 const options = children.reduce(
104 104 (arr, el) => [...arr, ...findOptionsInVNode(el)], []
105 105 ).filter(Boolean);
... ... @@ -123,6 +123,18 @@
123 123 };
124 124 };
125 125  
  126 + const getNestedProperty = (obj, path) => {
  127 + const keys = path.split('.');
  128 + return keys.reduce((o, key) => o && o[key] || null, obj);
  129 + };
  130 +
  131 + const getOptionLabel = option => {
  132 + const textContent = (option.componentOptions.children || []).reduce((str, child) => str + (child.text || ''), '');
  133 + const innerHTML = getNestedProperty(option, 'data.domProps.innerHTML');
  134 + return option.componentOptions.propsData.label || textContent || (typeof innerHTML === 'string' ? innerHTML : '');
  135 + };
  136 +
  137 +
126 138 const ANIMATION_TIMEOUT = 300;
127 139  
128 140 export default {
... ... @@ -210,8 +222,11 @@
210 222 this.$on('on-select-selected', this.onOptionClick);
211 223  
212 224 // set the initial values if there are any
213   - if (this.values.length > 0 && !this.remote && this.selectOptions.length > 0){
214   - this.values = this.values.map(this.getOptionData).filter(Boolean);
  225 + if (!this.remote && this.selectOptions.length > 0){
  226 + this.values = this.getInitialValue().map(value => {
  227 + if (typeof value !== 'number' && !value) return null;
  228 + return this.getOptionData(value);
  229 + }).filter(Boolean);
215 230 }
216 231  
217 232 if (this.values.length > 0 && this.selectOptions.length === 0){
... ... @@ -222,7 +237,7 @@
222 237  
223 238 return {
224 239 prefixCls: prefixCls,
225   - values: this.getInitialValue(),
  240 + values: [],
226 241 dropDownWidth: 0,
227 242 visible: false,
228 243 focusIndex: -1,
... ... @@ -400,8 +415,7 @@
400 415 getOptionData(value){
401 416 const option = this.flatOptions.find(({componentOptions}) => componentOptions.propsData.value === value);
402 417 if (!option) return null;
403   - const textContent = option.componentOptions.children.reduce((str, child) => str + (child.text || ''), '');
404   - const label = option.componentOptions.propsData.label || textContent || '';
  418 + const label = getOptionLabel(option);
405 419 return {
406 420 value: value,
407 421 label: label,
... ... @@ -621,14 +635,12 @@
621 635 values(now, before){
622 636 const newValue = JSON.stringify(now);
623 637 const oldValue = JSON.stringify(before);
624   - const shouldEmitInput = newValue !== oldValue;
625   -
  638 + // v-model is always just the value, event with labelInValue === true
  639 + const vModelValue = (this.publicValue && this.labelInValue) ?
  640 + (this.multiple ? this.publicValue.map(({value}) => value) : this.publicValue.value) :
  641 + this.publicValue;
  642 + const shouldEmitInput = newValue !== oldValue && vModelValue !== this.value;
626 643 if (shouldEmitInput) {
627   - // v-model is always just the value, event with labelInValue === true
628   - const vModelValue = this.labelInValue ?
629   - (this.multiple ? this.publicValue.map(({value}) => value)
630   - :
631   - this.publicValue.value) : this.publicValue;
632 644 this.$emit('input', vModelValue); // to update v-model
633 645 this.$emit('on-change', this.publicValue);
634 646 this.dispatch('FormItem', 'on-form-change', this.publicValue);
... ...
test/unit/specs/select.spec.js
... ... @@ -47,7 +47,7 @@ describe('Select.vue', () => {
47 47 waitForIt(
48 48 () => {
49 49 const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value');
50   - return selectedValueSpan.textContent === 'Bar';
  50 + return selectedValueSpan && selectedValueSpan.textContent === 'Bar';
51 51 },
52 52 () => {
53 53 const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value');
... ... @@ -121,7 +121,7 @@ describe('Select.vue', () => {
121 121 waitForIt(
122 122 () => {
123 123 const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value');
124   - return selectedValueSpan.textContent === 'Bar';
  124 + return selectedValueSpan && selectedValueSpan.textContent === 'Bar';
125 125 },
126 126 () => {
127 127 const placeholderSpan = vm.$el.querySelector('.ivu-select-placeholder');
... ...