Select
下拉框组件
Markup Schema 同步数据源案例
*
:请选择
vue
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
required
name="select"
title="选择框"
x-decorator="FormItem"
x-component="Select"
:x-component-props="{
style: {
width: '240px',
},
clearable: true,
onChange: (e) => {
console.log('change')
},
}"
:enum="[
{
label: '选项1',
value: 1,
},
{
label: '选项2',
value: 2,
},
]"
/>
</SchemaField>
<Submit @submit="log">提交</Submit>
</FormProvider>
</template>
<script>
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
const fields = createSchemaField({
components: {
FormItem,
Select,
},
})
export default {
components: { FormProvider, ...fields, Submit },
data() {
return {
form,
}
},
methods: {
log(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
Markup Schema 异步搜索案例
:
请选择
vue
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="select"
title="异步搜索选择框"
x-decorator="FormItem"
x-component="Select"
:x-component-props="{
filterable: true,
remote: true,
style: {
width: '240px',
},
}"
/>
</SchemaField>
<Submit @submit="log">提交</Submit>
</FormProvider>
</template>
<script>
import { createForm, onFieldInit, onFieldReact } from '@formily/core'
import { action, observable } from '@formily/reactive'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
let timeout
let currentValue
function fetchData(value, callback) {
if (timeout) {
clearTimeout(timeout)
timeout = null
}
currentValue = value
function fake() {
callback([
{
label: 'AAA',
value: 'aaa',
},
{
label: 'BBB',
value: 'ccc',
},
])
}
timeout = setTimeout(fake, 300)
}
const useAsyncDataSource = (pattern, service) => {
const keyword = observable.ref('')
onFieldInit(pattern, (field) => {
field.setComponentProps({
remoteMethod: (value) => {
keyword.value = value
},
})
})
onFieldReact(pattern, (field) => {
field.loading = true
service({ field, keyword: keyword.value }).then(
action.bound((data) => {
field.dataSource = data
field.loading = false
})
)
})
}
const form = createForm({
effects: () => {
useAsyncDataSource('select', async ({ keyword }) => {
if (!keyword) {
return []
}
return new Promise((resolve) => {
fetchData(keyword, resolve)
})
})
},
})
const fields = createSchemaField({
components: {
FormItem,
Select,
},
})
export default {
components: { FormProvider, ...fields, Submit },
data() {
return {
form,
}
},
methods: {
log(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
Markup Schema 异步搜索案例
组件属性remoteMethod
的写法
:
请选择
vue
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="select"
title="异步搜索选择框"
x-decorator="FormItem"
x-component="Select"
:x-component-props="{
filterable: true,
remote: true,
remoteMethod: remoteMethod,
style: {
width: '240px',
},
}"
/>
</SchemaField>
<Submit @submit="log">提交</Submit>
</FormProvider>
</template>
<script setup lang="ts">
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
import type { Field } from '@formily/core'
const { FormItem, Select, Submit } = Formily
const states = [
'Alabama',
'Alaska',
'Arizona',
'Arkansas',
'California',
'Colorado',
'Connecticut',
'Delaware',
'Florida',
'Georgia',
'Hawaii',
'Idaho',
'Illinois',
'Indiana',
'Iowa',
'Kansas',
'Kentucky',
'Louisiana',
'Maine',
'Maryland',
'Massachusetts',
'Michigan',
'Minnesota',
'Mississippi',
'Missouri',
'Montana',
'Nebraska',
'Nevada',
'New Hampshire',
'New Jersey',
'New Mexico',
'New York',
'North Carolina',
'North Dakota',
'Ohio',
'Oklahoma',
'Oregon',
'Pennsylvania',
'Rhode Island',
'South Carolina',
'South Dakota',
'Tennessee',
'Texas',
'Utah',
'Vermont',
'Virginia',
'Washington',
'West Virginia',
'Wisconsin',
'Wyoming',
]
const list = states.map((item) => {
return { value: `value:${item}`, label: `label:${item}` }
})
let tick: any
const remoteMethod = (query: string) => {
const field = form.query('*').take() as Field
if (query) {
clearTimeout(tick)
field.loading = true
tick = setTimeout(() => {
if (field) {
field.setDataSource(
list.filter((item) => {
return item.label.toLowerCase().includes(query.toLowerCase())
})
)
field.loading = false
}
}, 200)
} else {
if (field) {
field.setDataSource([])
}
}
}
const form = createForm({})
const fields = createSchemaField({
components: {
FormItem,
Select,
},
})
const { SchemaField, SchemaStringField } = fields
const log = (value: Record<string, any>) => {
console.log(value)
}
</script>
隐藏源代码
Markup Schema 异步联动数据源案例
vue
<template>
<Form :form="form">
<SchemaField>
<SchemaNumberField
name="linkage"
title="联动选择框"
x-decorator="FormItem"
x-component="Select"
:enum="[
{ label: '发请求1', value: 1 },
{ label: '发请求2', value: 2 },
]"
:x-component-props="{
style: {
width: '240px',
},
}"
/>
<SchemaStringField
name="select"
title="异步选择框"
x-decorator="FormItem"
x-component="Select"
:x-component-props="{
style: {
width: '240px',
},
}"
/>
</SchemaField>
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const useAsyncDataSource = (pattern, service) => {
onFieldReact(pattern, (field) => {
field.loading = true
service(field).then(
action.bound((data) => {
field.dataSource = data
field.loading = false
})
)
})
}
const form = createForm({
effects: () => {
useAsyncDataSource('select', async (field) => {
const linkage = field.query('linkage').get('value')
if (!linkage) return []
field.query('select').take().setValue('')
return new Promise((resolve) => {
setTimeout(() => {
if (linkage === 1) {
resolve([
{
label: 'AAA',
value: 'aaa',
},
{
label: 'BBB',
value: 'ccc',
},
])
} else if (linkage === 2) {
resolve([
{
label: 'CCC',
value: 'ccc',
},
{
label: 'DDD',
value: 'ddd',
},
])
}
}, 1500)
})
})
},
})
const fields = createSchemaField({
components: {
FormItem,
Select,
},
})
export default {
components: { Form, ...fields, Submit },
data() {
return {
form,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
Markup Schema 插槽案例
如果你想拿到插槽作用域属性值,render
函数必须至少有 2 个参数,这是受 ReactiveField组件 merge slots 的实现所约束
ts
const resolveComponent = (render: () => unknown[], extra?: any) => {
// ...
// for scoped slot
if (extra.length > 1 || extra?.render?.length > 1) {
return (scopedProps: VueComponentProps<any>) => [
...render(),
h(extra, { props: scopedProps }, {}),
]
}
// ...
}
支持 el-select
所有插槽,el-option
的默认插槽改成了 option
插槽(因为 el-select 也有默认插槽)
:
请选择
vue
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="select"
title="选择框"
x-decorator="FormItem"
x-component="Select"
:x-component-props="{
style: {
width: '240px',
},
}"
:enum="[
{
label: '选项1',
value: 1,
},
{
label: '选项2',
value: 2,
},
]"
:x-content="content"
/>
</SchemaField>
<Submit @submit="log">提交</Submit>
</FormProvider>
</template>
<script setup>
import { h } from 'vue'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
const fields = createSchemaField({
components: {
FormItem,
Select,
},
})
const { SchemaField, SchemaStringField } = fields
const log = (value) => {
console.log(value)
}
const content = {
// option为 el-option 组件的默认插槽
option: {
props: ['option'],
render(thisProxy, proxyToUse) {
const { option } = thisProxy
return h('div', {}, `${option.label}-${option.value}`)
},
},
header: {
render() {
return h('div', {}, `header`)
},
},
}
</script>
隐藏源代码
JSON Schema 同步数据源案例
vue
<template>
<Form :form="form">
<SchemaField :schema="schema" />
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const schema = {
type: 'object',
properties: {
select: {
type: 'string',
title: '选择框',
enum: [
{
label: '选项1',
value: 1,
},
{
label: '选项2',
value: 2,
},
],
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-component-props': {
style: 'width: 240px;',
clearable: true,
},
},
},
}
const form = createForm()
const { SchemaField } = createSchemaField({
components: {
FormItem,
Select,
},
})
export default {
components: { Form, SchemaField, Submit },
data() {
return {
form,
schema,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
JSON Schema 异步联动数据源案例
vue
<template>
<Form :form="form">
<SchemaField :schema="schema" :scope="{ useAsyncDataSource, loadData }" />
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm } from '@formily/core'
import { createSchemaField } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const schema = {
type: 'object',
properties: {
linkage: {
type: 'string',
title: '联动选择框',
enum: [
{
label: '发请求1',
value: 1,
},
{
label: '发请求2',
value: 2,
},
],
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-component-props': {
style: 'width: 240px;',
},
},
select: {
type: 'string',
title: '异步选择框',
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-component-props': {
style: 'width: 240px;',
},
'x-reactions': ['{{useAsyncDataSource(loadData)}}'],
},
},
}
const useAsyncDataSource = (service) => (field) => {
field.loading = true
service(field).then(
action.bound((data) => {
field.dataSource = data
field.loading = false
})
)
}
const loadData = async (field) => {
const linkage = field.query('linkage').get('value')
if (!linkage) return []
return new Promise((resolve) => {
setTimeout(() => {
if (linkage === 1) {
resolve([
{
label: 'AAA',
value: 'aaa',
},
{
label: 'BBB',
value: 'ccc',
},
])
} else if (linkage === 2) {
resolve([
{
label: 'CCC',
value: 'ccc',
},
{
label: 'DDD',
value: 'ddd',
},
])
}
}, 1500)
})
}
const form = createForm()
const { SchemaField } = createSchemaField({
components: {
FormItem,
Select,
},
})
export default {
components: { Form, SchemaField, Submit },
data() {
return {
form,
schema,
}
},
methods: {
useAsyncDataSource,
loadData,
onSubmit(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
Template 同步数据源案例
:
请选择
vue
<template>
<FormProvider :form="form">
<Field
name="select"
title="选择框"
:decorator="[FormItem]"
:component="[
Select,
{
style: {
width: '240px',
},
clearable: true,
},
]"
:data-source="[
{
label: '选项1',
value: 1,
},
{
label: '选项2',
value: 2,
},
]"
/>
<Submit @submit="log">提交</Submit>
</FormProvider>
</template>
<script>
import { createForm } from '@formily/core'
import { Field, FormProvider } from '@formily/vue'
import { Formily } from 'element-plus-x'
const { FormItem, Select, Submit } = Formily
const form = createForm()
export default {
components: { FormProvider, Field, Submit },
data() {
return {
FormItem,
Select,
form,
}
},
methods: {
log(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
Template 异步联动数据源案例
vue
<template>
<Form :form="form">
<Field
name="linkage"
title="联动选择框"
:decorator="[FormItem]"
:component="[
Select,
{
style: {
width: '240px',
},
},
]"
:data-source="[
{ label: '发请求1', value: 1 },
{ label: '发请求2', value: 2 },
]"
/>
<Field
name="select"
title="异步选择框"
:decorator="[FormItem]"
:component="[
Select,
{
style: {
width: '240px',
},
},
]"
/>
<Submit @submit="onSubmit">提交</Submit>
</Form>
</template>
<script>
import { createForm, onFieldReact } from '@formily/core'
import { Field } from '@formily/vue'
import { action } from '@formily/reactive'
import { Formily } from 'element-plus-x'
const { Form, FormItem, Select, Submit } = Formily
const useAsyncDataSource = (pattern, service) => {
onFieldReact(pattern, (field) => {
field.loading = true
service(field).then(
action.bound((data) => {
field.dataSource = data
field.loading = false
})
)
})
}
const form = createForm({
effects: () => {
useAsyncDataSource('select', async (field) => {
const linkage = field.query('linkage').get('value')
if (!linkage) return []
return new Promise((resolve) => {
setTimeout(() => {
if (linkage === 1) {
resolve([
{
label: 'AAA',
value: 'aaa',
},
{
label: 'BBB',
value: 'ccc',
},
])
} else if (linkage === 2) {
resolve([
{
label: 'CCC',
value: 'ccc',
},
{
label: 'DDD',
value: 'ddd',
},
])
}
}, 1500)
})
})
},
})
export default {
components: { Form, Field, Submit },
data() {
return {
form,
FormItem,
Select,
}
},
methods: {
onSubmit(value) {
console.log(value)
},
},
}
</script>
隐藏源代码
API
参考 ElSelect