fix select

This commit is contained in:
tjz 2018-02-07 23:03:47 +08:00
parent 13cc2ada5a
commit f4187ee1fe
8 changed files with 131 additions and 86 deletions

View File

@ -17,8 +17,12 @@ const filterProps = (props, propsData = {}) => {
})
return res
}
const getSlotOptions = (slot) => {
return slot.componentOptions.Ctor.options
const getSlotOptions = (ele) => {
let componentOptions = ele.componentOptions
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions.Ctor.options
}
const getOptionProps = (instance) => {
const { $options = {}, $props = {}} = instance
@ -35,8 +39,18 @@ const getComponentFromProp = (instance, prop) => {
}
const getPropsData = (ele) => {
return ele.componentOptions && ele.componentOptions.propsData
let componentOptions = ele.componentOptions
if (ele.$vnode) {
componentOptions = ele.$vnode.componentOptions
}
return componentOptions && componentOptions.propsData
}
export { hasProp, filterProps, getOptionProps, getComponentFromProp, getSlotOptions, slotHasProp, getPropsData }
const getKey = (ele) => {
let key = ele.key
if (ele.$vnode) {
key = ele.$vnode.key
}
return key
}
export { hasProp, filterProps, getOptionProps, getComponentFromProp, getSlotOptions, slotHasProp, getPropsData, getKey }
export default hasProp

View File

@ -87,7 +87,7 @@ export default {
if (!transitionName) {
if (typeof animation === 'string') {
transitionName = `${animation}`
} else if (animation.props && animation.props.name) {
} else if (animation && animation.props && animation.props.name) {
transitionName = animation.props.name
}
}

View File

@ -51,9 +51,8 @@ export default {
// }
updated () {
const prevProps = this.prevProps
const props = this.$props
if (!prevProps.visible && props.visible) {
if (!this.prevVisible && props.visible) {
this.$nextTick(() => {
this.scrollActiveItemToView()
})
@ -64,7 +63,7 @@ export default {
methods: {
scrollActiveItemToView () {
// scroll into view
const itemComponent = this.$refs.firstActiveItem.$el
const itemComponent = this.$refs.firstActiveItem && this.$refs.firstActiveItem.$el
const props = this.$props
if (itemComponent) {
@ -170,6 +169,7 @@ export default {
},
render () {
const renderMenu = this.renderMenu()
this.prevVisible = this.visible
const { popupFocus, popupScroll } = this.$listeners
return renderMenu ? (
<div

View File

@ -65,6 +65,7 @@ export default {
notFoundContent: PropTypes.string.def('Not Found'),
backfill: PropTypes.bool.def(false),
showAction: SelectPropTypes.showAction.def(['click']),
combobox: PropTypes.bool.def(false),
// onChange: noop,
// onFocus: noop,
// onBlur: noop,
@ -105,26 +106,30 @@ export default {
this.autoFocus && this.focus()
})
},
beforeUpdate () {
if (hasProp(this, 'value')) {
const { combobox, $slots } = this
let value = toArray(this.value)
value = this.addLabelToValue(value)
value = this.addTitleToValue($slots, value)
this.setState({
sValue: value,
})
if (combobox) {
this.setState({
inputValue: value.length
? this.getLabelFromProps(value[0].key)
: '',
})
}
}
this.adjustOpenState()
watch: {
'$props': {
handler: function (nextProps) {
if (hasProp(this, 'value')) {
const { combobox, $slots } = this
let value = toArray(this.value)
value = this.addLabelToValue(value)
value = this.addTitleToValue($slots, value)
this.setState({
sValue: value,
})
if (combobox) {
this.setState({
inputValue: value.length
? this.getLabelFromProps(value[0].key)
: '',
})
}
}
this.adjustOpenState()
},
deep: true,
},
},
updated () {
this.$nextTick(() => {
if (isMultipleOrTags(this.$props)) {
@ -259,7 +264,7 @@ export default {
}
}
this.__emit('select', event, item)
const selectedTitle = item.props.title
const selectedTitle = item.title
if (isMultipleOrTags(props)) {
if (findIndexInValueByKey(sValue, selectedValue) !== -1) {
return
@ -416,7 +421,6 @@ export default {
if (!child) {
return
}
console.log('child', child)
if (getSlotOptions(child).isSelectOptGroup) {
const maybe = this.getLabelBySingleValue(child.componentOptions.children, value)
if (maybe !== null) {
@ -501,17 +505,23 @@ export default {
hidden = false
}
if (placeholder) {
const p = {
props: {
},
on: {
mousedown: preventDefaultEvent,
click: this.onPlaceholderClick,
},
attrs: UNSELECTABLE_ATTRIBUTE,
style: {
display: hidden ? 'none' : 'block',
...UNSELECTABLE_STYLE,
},
class: `${prefixCls}-selection__placeholder`,
}
return (
<div
onMousedown={preventDefaultEvent}
style={{
display: hidden ? 'none' : 'block',
...UNSELECTABLE_STYLE,
}}
{...UNSELECTABLE_ATTRIBUTE}
onClick={this.onPlaceholderClick}
class={`${prefixCls}-selection__placeholder`}
>
<div {...p}>
{placeholder}
</div>
)
@ -540,8 +550,8 @@ export default {
class: inputCls,
ref: 'inputRef',
on: {
change: this.onInputChange,
keyDown: chaining(
input: this.onInputChange,
keydown: chaining(
this.onInputKeydown,
getEvents(inputElement).keydown || noop,
this.$listeners.inputKeydown
@ -611,7 +621,7 @@ export default {
},
focus () {
if (isSingleMode(this.props)) {
if (isSingleMode(this.$props)) {
this.$refs.selectionRef.focus()
} else {
this.getInputDOMNode().focus()
@ -619,7 +629,7 @@ export default {
},
blur () {
if (isSingleMode(this.props)) {
if (isSingleMode(this.$props)) {
this.$refs.selectionRef.blur()
} else {
this.getInputDOMNode().blur()
@ -717,7 +727,7 @@ export default {
if (needFocus || open) {
const input = this.getInputDOMNode()
const { activeElement } = document
if (input && (open || isMultipleOrTagsOrCombobox(this.props))) {
if (input && (open || isMultipleOrTagsOrCombobox(this.$props))) {
if (activeElement !== input) {
input.focus()
this._focused = true
@ -890,7 +900,7 @@ export default {
const menuItem = (
<MenuItem
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
{...{ attrs: UNSELECTABLE_ATTRIBUTE }}
value={key}
key={key}
>
@ -917,13 +927,16 @@ export default {
return !filterFn()
})
if (notFindInputItem) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: inputValue,
props: {
value: inputValue,
},
style: UNSELECTABLE_STYLE,
}
options.unshift(
<MenuItem
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
value={inputValue}
key={inputValue}
>
<MenuItem {...p}>
{inputValue}
</MenuItem>
)
@ -932,14 +945,17 @@ export default {
}
if (!options.length && notFoundContent) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: 'NOT_FOUND',
props: {
value: 'NOT_FOUND',
disabled: true,
},
style: UNSELECTABLE_STYLE,
}
options = [
<MenuItem
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
disabled
value='NOT_FOUND'
key='NOT_FOUND'
>
<MenuItem {...p}>
{notFoundContent}
</MenuItem>,
]
@ -978,11 +994,10 @@ export default {
}
return
}
warning(
getSlotOptions(child).isSelectOptGroup,
getSlotOptions(child).isSelectOption,
'the children of `Select` should be `Select.Option` or `Select.OptGroup`, ' +
`instead of \`${getSlotOptions(child).isSelectOptGroup ||
`instead of \`${getSlotOptions(child).name ||
getSlotOptions(child)}\`.`
)
@ -991,14 +1006,18 @@ export default {
validateOptionValue(childValue, this.$props)
if (this._filterOption(inputValue, child)) {
const p = {
attrs: UNSELECTABLE_ATTRIBUTE,
key: childValue,
props: {
value: childValue,
...getPropsData(child),
},
style: UNSELECTABLE_STYLE,
on: getEvents(child),
}
const menuItem = (
<MenuItem
style={UNSELECTABLE_STYLE}
attribute={UNSELECTABLE_ATTRIBUTE}
value={childValue}
key={childValue}
{...getPropsData(child)}
/>
<MenuItem {...p}>{child.componentOptions.children}</MenuItem>
)
sel.push(menuItem)
menuItems.push(menuItem)
@ -1086,8 +1105,8 @@ export default {
}
maxTagPlaceholderEl = (<li
style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE}
onMouseDown={preventDefaultEvent}
unselectable='unselectable'
onMousedown={preventDefaultEvent}
class={`${prefixCls}-selection__choice ${prefixCls}-selection__choice__disabled`}
key={'maxTagPlaceholder'}
title={content}
@ -1113,7 +1132,7 @@ export default {
return (
<li
style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE}
unselectable='unselectable'
onMousedown={preventDefaultEvent}
class={choiceClassName}
key={singleValue.key}
@ -1146,6 +1165,7 @@ export default {
if (isMultipleOrTags(props) && choiceTransitionName) {
const transitionProps = getTransitionProps(choiceTransitionName, {
tag: 'ul',
afterLeave: this.onChoiceAnimationLeave,
})
innerNode = (
<transition-group
@ -1180,7 +1200,7 @@ export default {
key='clear'
onMousedown={preventDefaultEvent}
style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE}
unselectable='unselectable'
class={`${prefixCls}-selection__clear`}
onClick={this.onClearSelection}
/>
@ -1279,7 +1299,7 @@ export default {
key='arrow'
class={`${prefixCls}-arrow`}
style={UNSELECTABLE_STYLE}
{...UNSELECTABLE_ATTRIBUTE}
unselectable='unselectable'
onClick={this.onArrowClick}
>
<b />

View File

@ -32,17 +32,21 @@ export default {
// onPopupFocus: PropTypes.func,
// onPopupScroll: PropTypes.func,
dropdownMatchSelectWidth: PropTypes.bool,
defaultActiveFirstOption: PropTypes.bool,
dropdownAlign: PropTypes.object,
visible: PropTypes.bool,
disabled: PropTypes.bool,
showSearch: PropTypes.bool,
dropdownClassName: PropTypes.string,
dropdownStyle: PropTypes.object,
dropdownMenuStyle: PropTypes.object,
multiple: PropTypes.bool,
inputValue: PropTypes.string,
filterOption: PropTypes.any,
options: PropTypes.any,
prefixCls: PropTypes.string,
popupClassName: PropTypes.string,
value: PropTypes.array,
// children: PropTypes.any,
showAction: PropTypes.arrayOf(PropTypes.string),
},

View File

@ -35,10 +35,10 @@ export default {
<p>
<button onClick={this.toggleDisabled}>toggle disabled</button>
</p>
<div style={{ width: 300 }}>
<div style={{ width: '300px' }}>
<Select
disabled={this.disabled}
style={{ width: 500 }}
style={{ width: '500px' }}
onChange={this.onChange}
onSelect={this.onSelect}
onInputKeydown={this.onKeyDown}

View File

@ -1,11 +1,11 @@
import { getPropsData, getSlotOptions } from '../_util/props-util'
import { getPropsData, getSlotOptions, getKey } from '../_util/props-util'
export function getValuePropValue (child) {
const props = getPropsData(child)
if ('value' in props) {
return props.value
}
if (child.key) {
return child.key
if (getKey(child)) {
return getKey(child)
}
if (getSlotOptions(child).isSelectOptGroup && props.label) {
return props.label
@ -84,9 +84,9 @@ export function getSelectKeys (menuItems, value) {
}
let selectedKeys = []
menuItems.forEach(item => {
if (item.type.isMenuItemGroup) {
if (getSlotOptions(item).isMenuItemGroup) {
selectedKeys = selectedKeys.concat(
getSelectKeys(item.props.children, value)
getSelectKeys(item.componentOptions.children, value)
)
} else {
const itemValue = getValuePropValue(item)
@ -111,12 +111,13 @@ export const UNSELECTABLE_ATTRIBUTE = {
export function findFirstMenuItem (children) {
for (let i = 0; i < children.length; i++) {
const child = children[i]
if (child.type.isMenuItemGroup) {
const found = findFirstMenuItem(child.props.children)
const props = getSlotOptions(child)
if (props.isMenuItemGroup) {
const found = findFirstMenuItem(child.componentOptions.children)
if (found) {
return found
}
} else if (!child.props.disabled) {
} else if (!props.disabled) {
return child
}
}
@ -138,10 +139,11 @@ export function splitBySeparators (string, separators) {
}
export function defaultFilterFn (input, child) {
if (child.props.disabled) {
const props = getSlotOptions(child)
if (props.disabled) {
return false
}
const value = String(getPropValue(child, this.props.optionFilterProp))
const value = String(getPropValue(child, this.optionFilterProp))
return (
value.toLowerCase().indexOf(input.toLowerCase()) > -1
)

5
package-lock.json generated
View File

@ -2051,6 +2051,11 @@
}
}
},
"classnames": {
"version": "2.2.5",
"resolved": "http://registry.npm.taobao.org/classnames/download/classnames-2.2.5.tgz",
"integrity": "sha1-+zgB1FNGdknvNgPH1hoCvRKb3m0="
},
"clean-css": {
"version": "4.1.9",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.1.9.tgz",