diff --git a/src/components/select/select.vue b/src/components/select/select.vue index 89d8e658..1b7bd5d6 100644 --- a/src/components/select/select.vue +++ b/src/components/select/select.vue @@ -82,7 +82,7 @@ import FunctionalOptions from './functional-options.vue'; const prefixCls = 'ivu-select'; - const optionRegexp = /^i-option$|^Option$/; + const optionRegexp = /^i-option$|^Option$/i; const optionGroupRegexp = /option-?group/i; const findChild = (instance, checkFn) => { @@ -99,7 +99,7 @@ const opts = node.componentOptions; if (opts && opts.tag.match(optionRegexp)) return [node]; if (!node.children && (!opts || !opts.children)) return []; - const children = [...(node.children || []), ...(opts && opts.children || [])]; + const children = [...(node.children || []), ...(opts && opts.children || [])]; const options = children.reduce( (arr, el) => [...arr, ...findOptionsInVNode(el)], [] ).filter(Boolean); @@ -123,6 +123,18 @@ }; }; + const getNestedProperty = (obj, path) => { + const keys = path.split('.'); + return keys.reduce((o, key) => o && o[key] || null, obj); + }; + + const getOptionLabel = option => { + const textContent = (option.componentOptions.children || []).reduce((str, child) => str + (child.text || ''), ''); + const innerHTML = getNestedProperty(option, 'data.domProps.innerHTML'); + return option.componentOptions.propsData.label || textContent || (typeof innerHTML === 'string' ? innerHTML : ''); + }; + + const ANIMATION_TIMEOUT = 300; export default { @@ -210,8 +222,11 @@ this.$on('on-select-selected', this.onOptionClick); // set the initial values if there are any - if (this.values.length > 0 && !this.remote && this.selectOptions.length > 0){ - this.values = this.values.map(this.getOptionData).filter(Boolean); + if (!this.remote && this.selectOptions.length > 0){ + this.values = this.getInitialValue().map(value => { + if (typeof value !== 'number' && !value) return null; + return this.getOptionData(value); + }).filter(Boolean); } if (this.values.length > 0 && this.selectOptions.length === 0){ @@ -222,7 +237,7 @@ return { prefixCls: prefixCls, - values: this.getInitialValue(), + values: [], dropDownWidth: 0, visible: false, focusIndex: -1, @@ -400,8 +415,7 @@ getOptionData(value){ const option = this.flatOptions.find(({componentOptions}) => componentOptions.propsData.value === value); if (!option) return null; - const textContent = option.componentOptions.children.reduce((str, child) => str + (child.text || ''), ''); - const label = option.componentOptions.propsData.label || textContent || ''; + const label = getOptionLabel(option); return { value: value, label: label, @@ -619,14 +633,12 @@ values(now, before){ const newValue = JSON.stringify(now); const oldValue = JSON.stringify(before); - const shouldEmitInput = newValue !== oldValue; - + // v-model is always just the value, event with labelInValue === true + const vModelValue = (this.publicValue && this.labelInValue) ? + (this.multiple ? this.publicValue.map(({value}) => value) : this.publicValue.value) : + this.publicValue; + const shouldEmitInput = newValue !== oldValue && vModelValue !== this.value; if (shouldEmitInput) { - // v-model is always just the value, event with labelInValue === true - const vModelValue = this.labelInValue ? - (this.multiple ? this.publicValue.map(({value}) => value) - : - this.publicValue.value) : this.publicValue; this.$emit('input', vModelValue); // to update v-model this.$emit('on-change', this.publicValue); this.dispatch('FormItem', 'on-form-change', this.publicValue); diff --git a/test/unit/specs/select.spec.js b/test/unit/specs/select.spec.js index 003f1eab..06cbe13c 100644 --- a/test/unit/specs/select.spec.js +++ b/test/unit/specs/select.spec.js @@ -47,7 +47,7 @@ describe('Select.vue', () => { waitForIt( () => { const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); - return selectedValueSpan.textContent === 'Bar'; + return selectedValueSpan && selectedValueSpan.textContent === 'Bar'; }, () => { const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); @@ -121,7 +121,7 @@ describe('Select.vue', () => { waitForIt( () => { const selectedValueSpan = vm.$el.querySelector('.ivu-select-selected-value'); - return selectedValueSpan.textContent === 'Bar'; + return selectedValueSpan && selectedValueSpan.textContent === 'Bar'; }, () => { const placeholderSpan = vm.$el.querySelector('.ivu-select-placeholder');