You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
314 lines
10 KiB
314 lines
10 KiB
import classNames from './classNames' |
|
import eventsMixin from './eventsMixin' |
|
|
|
const DEFAULT_TRIGGER = 'onClick' |
|
const CELL_NAME = '../cell/index' |
|
const FIELD_NAME = '../field/index' |
|
|
|
const defaultToolbar = { |
|
title: '请选择', |
|
cancelText: '取消', |
|
confirmText: '确定', |
|
} |
|
|
|
const defaultEvents = { |
|
onChange() {}, |
|
onConfirm() {}, |
|
onCancel() {}, |
|
onVisibleChange() {}, |
|
onValueChange() {}, |
|
} |
|
|
|
const defaultPlatformProps = { |
|
labelPropName: 'label', |
|
format(values, props) { |
|
return Array.isArray(values.displayValue) ? values.displayValue.join(',') : values.displayValue |
|
}, |
|
} |
|
|
|
const defaultFieldNames = { |
|
label: 'label', |
|
value: 'value', |
|
children: 'children', |
|
} |
|
|
|
export default function popupMixin(selector = '#wux-picker', platformProps = defaultPlatformProps) { |
|
return Behavior({ |
|
behaviors: [eventsMixin({ defaultEvents })], |
|
properties: { |
|
toolbar: { |
|
type: Object, |
|
value: defaultToolbar, |
|
}, |
|
trigger: { |
|
type: String, |
|
value: DEFAULT_TRIGGER, |
|
}, |
|
defaultVisible: { |
|
type: Boolean, |
|
value: false, |
|
}, |
|
visible: { |
|
type: Boolean, |
|
value: false, |
|
}, |
|
controlled: { |
|
type: Boolean, |
|
value: false, |
|
}, |
|
disabled: { |
|
type: Boolean, |
|
value: false, |
|
}, |
|
}, |
|
data: { |
|
mounted: false, |
|
popupVisible: false, |
|
inputValue: [], |
|
}, |
|
methods: { |
|
/** |
|
* 设置组件显示或隐藏 |
|
*/ |
|
setVisibleState(popupVisible, callback = () => {}) { |
|
if (this.data.popupVisible !== popupVisible) { |
|
const params = { |
|
mounted: true, |
|
inputValue: this.data.value, // forceUpdate |
|
popupVisible, |
|
} |
|
this.setData(popupVisible ? params : { popupVisible }, () => { |
|
// collect field component & forceUpdate |
|
if (popupVisible && this.hasFieldDecorator) { |
|
const field = this.getFieldElem() |
|
if (field) { |
|
field.changeValue(field.data.value) |
|
} |
|
} |
|
callback() |
|
}) |
|
} |
|
}, |
|
/** |
|
* 触发 visibleChange 事件 |
|
*/ |
|
fireVisibleChange(popupVisible) { |
|
if (this.data.popupVisible !== popupVisible) { |
|
if (!this.data.controlled) { |
|
this.setVisibleState(popupVisible) |
|
} |
|
this.setScrollValue(undefined) |
|
this.triggerEvent('visibleChange', { visible: popupVisible }) |
|
} |
|
}, |
|
/** |
|
* 打开 |
|
*/ |
|
open() { |
|
this.fireVisibleChange(true) |
|
}, |
|
/** |
|
* 关闭 |
|
*/ |
|
close(callback) { |
|
if (typeof callback === 'function') { |
|
const values = this.getPickerValue(this.scrollValue || this.data.inputValue) |
|
callback.call(this, this.formatPickerValue(values)) |
|
} |
|
this.fireVisibleChange(false) |
|
}, |
|
/** |
|
* 组件关闭时重置其内部数据 |
|
*/ |
|
onClosed() { |
|
this.picker = null |
|
this.setData({ mounted: false, inputValue: null }) |
|
}, |
|
/** |
|
* 点击确定按钮时的回调函数 |
|
*/ |
|
onConfirm() { |
|
this.close((values) => { |
|
this.triggerEvent('change', values) // collect field component |
|
this.triggerEvent('confirm', values) |
|
}) |
|
}, |
|
/** |
|
* 点击取消按钮时的回调函数 |
|
*/ |
|
onCancel() { |
|
this.close((values) => this.triggerEvent('cancel', values)) |
|
}, |
|
/** |
|
* 每列数据选择变化后的回调函数 |
|
*/ |
|
onValueChange(e) { |
|
if (!this.data.mounted) return |
|
const { value } = e.detail |
|
if (this.data.cascade) { |
|
this.setCasecadeScrollValue(value) |
|
} else { |
|
this.setScrollValue(value) |
|
} |
|
|
|
this.updated(value, true) |
|
this.triggerEvent('valueChange', this.formatPickerValue(e.detail)) |
|
}, |
|
/** |
|
* 获取当前 picker 的值 |
|
*/ |
|
getPickerValue(value = this.data.inputValue) { |
|
this.picker = this.picker || this.selectComponent(selector) |
|
return this.picker && this.picker.getValue(value) |
|
}, |
|
/** |
|
* 格式化 picker 返回值 |
|
*/ |
|
formatPickerValue(values) { |
|
return { |
|
...values, |
|
[platformProps.labelPropName]: platformProps.format(values, this.data), |
|
} |
|
}, |
|
/** |
|
* 获取 field 父元素 |
|
*/ |
|
getFieldElem() { |
|
return this.field = (this.field || this.getRelationNodes(FIELD_NAME)[0]) |
|
}, |
|
/** |
|
* 设置子元素 props |
|
*/ |
|
setChildProps() { |
|
if (this.data.disabled) return |
|
const elements = this.getRelationNodes(CELL_NAME) |
|
const { trigger = DEFAULT_TRIGGER } = this.data |
|
if (elements.length > 0) { |
|
elements.forEach((inputElem) => { |
|
const { inputEvents } = inputElem.data |
|
const oriInputEvents = inputElem.data.oriInputEvents || { ...inputEvents } |
|
inputEvents[trigger] = (...args) => { |
|
if (oriInputEvents && oriInputEvents[trigger]) { |
|
oriInputEvents[trigger](...args) |
|
} |
|
this.onTriggerClick() |
|
} |
|
inputElem.setData({ oriInputEvents, inputEvents }) |
|
}) |
|
} |
|
}, |
|
/** |
|
* 触发事件 |
|
*/ |
|
onTriggerClick() { |
|
this.fireVisibleChange(!this.data.popupVisible) |
|
}, |
|
/** |
|
* 阻止移动触摸 |
|
*/ |
|
noop() {}, |
|
/** |
|
* 更新值 |
|
*/ |
|
updated(inputValue, isForce) { |
|
if (!this.hasFieldDecorator || isForce) { |
|
if (this.data.inputValue !== inputValue) { |
|
this.setData({ inputValue }) |
|
} |
|
} |
|
}, |
|
/** |
|
* 记录每列数据的变化值 |
|
*/ |
|
setScrollValue(value) { |
|
this.scrollValue = value |
|
}, |
|
/** |
|
* 记录每列数据的变化值 - 针对于级联 |
|
*/ |
|
setCasecadeScrollValue(value) { |
|
if (value && this.scrollValue) { |
|
const length = this.scrollValue.length |
|
if (length === value.length && this.scrollValue[length - 1] === value[length - 1]) { |
|
return |
|
} |
|
} |
|
this.setScrollValue(value) |
|
}, |
|
}, |
|
lifetimes: { |
|
ready() { |
|
const { defaultVisible, visible, controlled, value } = this.data |
|
const popupVisible = controlled ? visible : defaultVisible |
|
|
|
// 若 defaultFieldNames 存在,则缓存之,并传递给子组件,只生效一次 |
|
if ('defaultFieldNames' in this.data) { |
|
this.setData({ |
|
fieldNames: Object.assign({}, defaultFieldNames, this.data.defaultFieldNames), |
|
}) |
|
} |
|
|
|
this.mounted = true |
|
this.scrollValue = undefined |
|
this.setVisibleState(popupVisible) |
|
this.setChildProps() |
|
}, |
|
detached() { |
|
this.mounted = false |
|
}, |
|
}, |
|
definitionFilter(defFields) { |
|
// set default child |
|
Object.assign(defFields.relations = (defFields.relations || {}), { |
|
[CELL_NAME]: { |
|
type: 'child', |
|
observer() { |
|
this.setChildProps() |
|
}, |
|
}, |
|
[FIELD_NAME]: { |
|
type: 'ancestor', |
|
}, |
|
}) |
|
|
|
// set default classes |
|
Object.assign(defFields.computed = (defFields.computed || {}), { |
|
classes: ['prefixCls', function(prefixCls) { |
|
const wrap = classNames(prefixCls) |
|
const toolbar = `${prefixCls}__toolbar` |
|
const inner = `${prefixCls}__inner` |
|
const cancel = classNames(`${prefixCls}__button`, { |
|
[`${prefixCls}__button--cancel`]: true, |
|
}) |
|
const confirm = classNames(`${prefixCls}__button`, { |
|
[`${prefixCls}__button--confirm`]: true, |
|
}) |
|
const hover = `${prefixCls}__button--hover` |
|
const title = `${prefixCls}__title` |
|
|
|
return { |
|
wrap, |
|
toolbar, |
|
inner, |
|
cancel, |
|
confirm, |
|
hover, |
|
title, |
|
} |
|
}], |
|
}) |
|
|
|
// set default observers |
|
Object.assign(defFields.observers = (defFields.observers || {}), { |
|
visible(popupVisible) { |
|
if (this.data.controlled) { |
|
this.setVisibleState(popupVisible) |
|
} |
|
}, |
|
value(value) { |
|
this.updated(value) |
|
}, |
|
}) |
|
}, |
|
}) |
|
}
|
|
|