@form-create/vant
Version:
VantUI版本低代码表单|FormCreate 是一个可以通过 JSON 生成具有动态渲染、数据收集、验证和提交功能的低代码表单生成组件。支持6个UI框架,适配移动端,并且支持生成任何 Vue 组件。内置20种常用表单组件和自定义组件,再复杂的表单都可以轻松搞定。
114 lines (103 loc) • 3.89 kB
JSX
import {defineComponent, ref, toRef, watch} from 'vue';
const NAME = 'fcCascader';
export default defineComponent({
name: NAME,
inheritAttrs: false,
props: {
placeholder: String,
disabled: Boolean,
clearable: Boolean,
fieldNames: Object,
modelValue: [String, Number],
options: Array,
minDate: [String, Date],
maxDate: [String, Date],
},
emits: ['update:modelValue', 'fc.el', 'change'],
setup(props, _) {
const show = ref(false);
const modelValue = toRef(props, 'modelValue');
const options = toRef(props, 'options');
const fieldNames = toRef(props, 'fieldNames', {});
const findOptions = (options, value, path) => {
for (let i = 0; i < options.length; i++) {
if (options[i][fieldNames.value.value || 'value'] === value) {
return [...path, options[i]];
} else if (options[i][fieldNames.value.children || 'children']) {
const find = findOptions(options[i][fieldNames.value.children || 'children'], value, [...path, options[i]]);
if (find) {
return find;
}
}
}
}
const updateInputValue = (n) => {
if (n == null || n === '') {
return '';
}
const path = findOptions(options.value, n, []);
return path ? path.map((option) => option[fieldNames.value.text || 'text']).join(' / ') : n;
}
const inputValue = ref(updateInputValue(modelValue.value));
watch(() => modelValue.value, (n) => {
inputValue.value = updateInputValue(n);
});
watch(() => options.value, () => {
if (modelValue.value != null && modelValue.value !== '') {
inputValue.value = updateInputValue(modelValue.value);
}
}, {deep: true});
const onInput = (val) => {
_.emit('update:modelValue', val);
_.emit('change', val);
}
return {
show,
inputValue,
options,
open() {
if (props.disabled) {
return;
}
show.value = true;
},
confirm({selectedOptions, value}) {
inputValue.value = selectedOptions.map((option) => option[fieldNames.value.text || 'text']).join(' / ');
show.value = false;
onInput(value);
},
clear(e) {
e.stopPropagation();
inputValue.value = '';
onInput('');
}
}
},
render() {
const clearIcon = () => {
return this.$props.clearable && this.inputValue ?
<i class="van-badge__wrapper van-icon van-icon-clear van-field__clear"
onClick={this.clear}></i> : undefined;
}
return <div class="_fc-cascader">
<van-field ref="el" placeholder={this.placeholder} readonly disabled={this.$props.disabled}
onClick={this.open}
model-value={this.inputValue} border={false} isLink v-slots={{
'right-icon': clearIcon
}}/>
<van-popup show={this.show} onUpdate:show={(v) => this.show = v} round position="bottom">
<van-cascader
{...this.$attrs}
modelValue={this.modelValue}
fieldNames={this.fieldNames}
options={this.options}
onClose={() => this.show = false}
onFinish={this.confirm}
/>
</van-popup>
</div>
},
mounted() {
this.$emit('fc.el', this.$refs.el);
}
});