榆山数据端小程序
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.
 
 

197 lines
5.6 KiB

import baseComponent from '../helpers/baseComponent'
import createFieldsStore from '../helpers/createFieldsStore'
const DEFAULT_TRIGGER = 'onChange'
function noop() {}
function getValueFromEvent(e) {
// To support custom element
if (!e || !e.detail) {
if ('value' in e) {
return e.value
}
return e
}
return e.detail.value
}
const children = [
'picker',
'date-picker',
'popup-select',
'radio-group',
'checkbox-group',
'switch',
'input',
'input-number',
'rater',
'slider',
'textarea',
]
const relations = children.map((name) => `../${name}/index`).reduce((acc, name) => {
return {
...acc,
[name]: {
type: 'descendant',
observer: function() {
this.debounce(this.changeValue)
},
},
}
}, {})
baseComponent({
useField: true,
relations: {
'../form/index': {
type: 'ancestor',
},
...relations,
},
properties: {
initialValue: {
type: null,
value: null,
observer: 'changeValue',
},
valuePropName: {
type: String,
value: 'inputValue',
},
trigger: {
type: String,
value: DEFAULT_TRIGGER,
},
},
methods: {
/**
* 获取子节点
*/
getNodes(relations = []) {
return relations.map((name) => this.getRelationNodes(name)[0]).filter((v) => !!v)
},
/**
* 更新 value 值,同步到子元素
*/
changeValue(value = this.data.value) {
const relations = this.getRelationsName(['descendant'])
const elements = this.getNodes(relations)
this.fieldsStore = this.fieldsStore || createFieldsStore()
this.setValue(value)
if (elements.length > 0) {
elements.forEach((inputElem) => {
inputElem.hasFieldDecorator = true
this.setValue(value, inputElem, this.data.valuePropName, () => {
this.forceUpdate(this.data.name, this.data, inputElem)
})
})
}
},
/**
* 设置 value 值
*/
setValue(value, elem = this, valuePropName = 'value', callback = noop) {
if (elem.data[valuePropName] !== value) {
elem.setData({ [valuePropName]: value }, callback)
} else {
callback()
}
},
/**
* 强制更新元素
*/
forceUpdate(name, fieldOption, inputElem) {
const { valuePropName } = fieldOption
const inputProps = this.getFieldDecorator(name, fieldOption, inputElem)
const inputValue = inputProps[valuePropName]
delete inputProps[valuePropName]
inputElem.setData(inputProps)
this.setValue(inputValue, inputElem, valuePropName)
},
/**
* 同步子元素
*/
onCollectCommon(name, action, args) {
const field = this.fieldsStore.getField(name)
const { inputElem, oriInputProps } = field
const { oriInputEvents } = oriInputProps
// trigger inputElem func
if (oriInputEvents && oriInputEvents[action]) {
oriInputEvents[action](...args)
}
const value = getValueFromEvent(...args)
const oldValue = this.fieldsStore.getFieldValue(name)
const parent = this.getRelationNodes('../form/index')[0]
// set field value
if (value !== oldValue) {
this.setValue(value)
this.setValue(value, inputElem, field.valuePropName)
// trigger onChange
if (parent) {
const changedValues = { [name]: value }
const allValues = this.fieldsStore.getFieldsValue()
parent.onChange(changedValues, { ...allValues, ...changedValues })
}
}
return {
name,
field: {
...field,
value,
},
}
},
/**
* 同步子元素
*/
onCollect(name_, action, ...args) {
const { name, field } = this.onCollectCommon(name_, action, args)
this.fieldsStore.setFields({ [name]: field })
},
/**
* 字段装饰器
*/
getFieldDecorator(name, fieldOption, inputElem) {
const field = this.fieldsStore.getField(name)
const { data: oriInputProps } = inputElem
const { trigger = DEFAULT_TRIGGER } = fieldOption
const meta = {
...field,
...fieldOption,
name,
oriInputProps,
inputElem,
}
this.fieldsStore.setFields({ [name]: meta })
const inputProps = {
...this.fieldsStore.getFieldValuePropValue(fieldOption),
}
// set input events, rewrite `trigger` func
if (trigger && !oriInputProps.oriInputEvents) {
inputProps.oriInputEvents = { ...oriInputProps.inputEvents }
inputProps.inputEvents = {
...oriInputProps.inputEvents,
[trigger]: (...args) => this.onCollect(name, trigger, ...args),
}
}
return inputProps
},
},
})