PickerSelect
弹窗版下拉选择框
Template
弹窗表格选择
<script setup lang="tsx">
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { Field, FormProvider } from '@silver-formily/vue'
const form = createForm()
const userRows = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const userOptions = userRows.map(item => ({
label: `${item.name} / ${item.team}`,
value: item.id,
raw: item,
}))
async function openUserPicker({ field }) {
const values_1 = await FormDialog('选择成员', () => (
<Field
name="users"
component={[
SelectTable,
{
rowKey: 'id',
optionAsValue: true,
columns: [
{ prop: 'name', label: '姓名' },
{ prop: 'team', label: '团队' },
],
},
]}
dataSource={userRows}
/>
))
.forOpen((form, next) => {
form.setValues({
users: userRows.filter(item => field?.value?.includes?.(item.id)),
})
next()
})
.open()
return values_1.users.map(item_1 => ({
label: `${item_1.name} / ${item_1.team}`,
value: item_1.id,
raw: item_1,
}))
}
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="users"
title="成员"
:decorator="[FormItem]"
:component="[
PickerSelect,
{
multiple: true,
clearable: true,
collapseTags: true,
collapseTagsTooltip: true,
openPicker: openUserPicker,
placeholder: '点击选择成员',
},
]"
:initial-value="['u1', 'u2', 'u3']"
:data-source="userOptions"
/>
<Submit style="margin-top: 16px" @submit="log">
提交
</Submit>
</FormProvider>
</template>成员:
查看源码
返回完整选项值 5.2.0
开启 optionAsValue 后,PickerSelect 对外提交的是 raw 原始对象,内部仍使用 value 进行返显。
<script setup lang="tsx">
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { Field, FormProvider } from '@silver-formily/vue'
const form = createForm()
const userRows = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const userOptions = userRows.map(item => ({
label: `${item.name} / ${item.team}`,
value: item.id,
raw: item,
}))
async function openUserPicker({ field }) {
const selectedIds = Array.isArray(field?.value)
? field.value.map(item => typeof item === 'object' ? item.id : item)
: []
const values_1 = await FormDialog('选择成员', () => (
<Field
name="users"
component={[
SelectTable,
{
rowKey: 'id',
optionAsValue: true,
columns: [
{ prop: 'name', label: '姓名' },
{ prop: 'team', label: '团队' },
],
},
]}
dataSource={userRows}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({
users: userRows.filter(item_1 => selectedIds.includes(item_1.id)),
})
next()
})
.open()
return values_1.users.map(item_2 => ({
label: `${item_2.name} / ${item_2.team}`,
value: item_2.id,
raw: item_2,
}))
}
function log(value: any) {
console.log('提交的完整用户对象:', value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="users"
title="成员"
:decorator="[FormItem]"
:component="[
PickerSelect,
{
multiple: true,
optionAsValue: true,
valueKey: 'id',
clearable: true,
collapseTags: true,
openPicker: openUserPicker,
placeholder: '选择成员后提交完整对象',
},
]"
:initial-value="userRows.slice(0, 2)"
:data-source="userOptions"
/>
<Submit style="margin-top: 16px" @submit="log">
提交完整对象
</Submit>
</FormProvider>
</template>成员:
查看源码
- 开启了
optionAsValue之后openPicker返回的 option 应提供raw。 - 如果原始对象的主键不是
id,可以通过valueKey指定主键字段。
单选弹窗表格选择
单选时 PickerSelect 的字段值是单个字符串、数字或对象,不会包装成数组。
<script setup lang="tsx">
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { Field, FormProvider } from '@silver-formily/vue'
const form = createForm()
const people = [
{ id: 101, name: 'Ada Lovelace', team: 'Math' },
{ id: 102, name: 'Grace Hopper', team: 'Compiler' },
{ id: 103, name: 'Linus Torvalds', team: 'Kernel' },
]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const values_1 = await FormDialog('选择负责人', () => (
<Field
name="person"
component={[SelectTable, {
mode: 'single',
rowKey: 'id',
showAlertToolbar: false,
columns: [
{ prop: 'name', label: '姓名' },
{ prop: 'team', label: '团队' },
],
}]}
dataSource={people}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
const item = people.find(item_1 => item_1.id === values_1.person)
return item ? { label: item.name, value: item.id, raw: item } : undefined
}
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="person"
title="负责人"
:decorator="[FormItem]"
:component="[PickerSelect, { openPicker, clearable: true, placeholder: '选择负责人' }]"
:initial-value="102"
:data-source="options"
/>
<Submit style="margin-top: 16px" @submit="log">
提交
</Submit>
</FormProvider>
</template>负责人:
查看源码
JSON Schema
标量值
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const values_1 = await FormDialog('选择负责人', () => <FieldDialog />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
const item = people.find(item_1 => item_1.id === values_1.person)
return item ? { label: item.name, value: item.id, raw: item } : undefined
}
function FieldDialog() {
return (
<Field
name="person"
component={[SelectTable, { mode: 'single', rowKey: 'id', showAlertToolbar: false, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]}
dataSource={people}
/>
)
}
const schema = { type: 'object', properties: { person: {
'type': 'string',
'title': '负责人',
'enum': options,
'default': 'u2',
'x-decorator': 'FormItem',
'x-component': 'PickerSelect',
'x-component-props': { openPicker },
} } }
const form = createForm()
const { SchemaField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" /><Submit @submit="log">
提交
</Submit>
</FormProvider>
</template>负责人:
查看源码
完整对象 5.2.0
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const values_1 = await FormDialog('选择负责人', () => (
<Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', optionAsValue: true, showAlertToolbar: false, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]} dataSource={people} />
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: people.find(item => item.id === field?.value?.id) })
next()
})
.open()
return values_1.person && { label: values_1.person.name, value: values_1.person.id, raw: values_1.person }
}
const schema = { type: 'object', properties: { person: {
'type': 'object',
'title': '负责人',
'enum': options,
'default': people[1],
'x-decorator': 'FormItem',
'x-component': 'PickerSelect',
'x-component-props': { optionAsValue: true, valueKey: 'id', openPicker },
} } }
const form = createForm()
const { SchemaField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" /><Submit @submit="log">
提交完整对象
</Submit>
</FormProvider>
</template>负责人:
查看源码
多选
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const selectedIds = Array.isArray(field?.value) ? field.value : []
const values_1 = await FormDialog('选择成员', () => (
<Field
name="people"
component={[SelectTable, { mode: 'multiple', rowKey: 'id', optionAsValue: true, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]}
dataSource={people}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ people: people.filter(item => selectedIds.includes(item.id)) })
next()
})
.open()
return values_1.people.map(item_1 => ({ label: item_1.name, value: item_1.id, raw: item_1 }))
}
const schema = { type: 'object', properties: { people: {
'type': 'array',
'title': '成员',
'items': { type: 'string' },
'enum': options,
'default': ['u1', 'u2'],
'x-decorator': 'FormItem',
'x-component': 'PickerSelect',
'x-component-props': { multiple: true, openPicker, collapseTags: true },
} } }
const form = createForm()
const { SchemaField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" /><Submit @submit="log">
提交
</Submit>
</FormProvider>
</template>成员:
查看源码
Markup Schema
标量值
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [{ id: 101, name: 'Ada Lovelace', team: 'Math' }, { id: 102, name: 'Grace Hopper', team: 'Compiler' }]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const values_1 = await FormDialog('选择负责人', () => <Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', showAlertToolbar: false, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
const item = people.find(item_1 => item_1.id === values_1.person)
return item ? { label: item.name, value: item.id, raw: item } : undefined
}
const form = createForm()
const { SchemaField, SchemaNumberField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField><SchemaNumberField name="person" title="负责人" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ openPicker, clearable: true }" :enum="options" :default="102" /></SchemaField>
<Submit @submit="log">
提交
</Submit>
</FormProvider>
</template>负责人:
查看源码
完整对象 5.2.0
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [{ id: 'u1', name: 'Ada Lovelace', team: 'Math' }, { id: 'u2', name: 'Grace Hopper', team: 'Compiler' }]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const values_1 = await FormDialog('选择负责人', () => <Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', optionAsValue: true, showAlertToolbar: false, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: people.find(item => item.id === field?.value?.id) })
next()
})
.open()
return values_1.person && { label: values_1.person.name, value: values_1.person.id, raw: values_1.person }
}
const form = createForm()
const { SchemaField, SchemaObjectField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField><SchemaObjectField name="person" title="负责人" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ optionAsValue: true, valueKey: 'id', openPicker }" :enum="options" :default="people[1]" /></SchemaField>
<Submit @submit="log">
提交完整对象
</Submit>
</FormProvider>
</template>负责人:
查看源码
多选
<script lang="tsx" setup>
import { createForm } from '@silver-formily/core'
import { FormDialog, FormItem, PickerSelect, SelectTable, Submit } from '@silver-formily/element-plus'
import { createSchemaField, Field, FormProvider } from '@silver-formily/vue'
const people = [
{ id: 'u1', name: 'Ada Lovelace', team: 'Math' },
{ id: 'u2', name: 'Grace Hopper', team: 'Compiler' },
{ id: 'u3', name: 'Linus Torvalds', team: 'Kernel' },
]
const options = people.map(item => ({ label: item.name, value: item.id, raw: item }))
async function openPicker({ field }) {
const selectedIds = Array.isArray(field?.value) ? field.value : []
const values_1 = await FormDialog('选择成员', () => <Field name="people" component={[SelectTable, { mode: 'multiple', rowKey: 'id', optionAsValue: true, columns: [{ prop: 'name', label: '姓名' }, { prop: 'team', label: '团队' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ people: people.filter(item => selectedIds.includes(item.id)) })
next()
})
.open()
return values_1.people.map(item_1 => ({ label: item_1.name, value: item_1.id, raw: item_1 }))
}
const form = createForm()
const { SchemaField, SchemaArrayField } = createSchemaField({ components: { FormItem, PickerSelect, SelectTable } })
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField><SchemaArrayField name="people" title="成员" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ multiple: true, openPicker, collapseTags: true }" :enum="options" :default="['u1', 'u2']" /></SchemaField>
<Submit @submit="log">
提交
</Submit>
</FormProvider>
</template>成员:
查看源码
API
参考 https://cn.element-plus.org/zh-CN/component/select.html
扩展属性
| 属性名 | 类型 | 描述 | 默认值 |
|---|---|---|---|
| options | PickerSelectOption[] | 候选项配置,一般情况下优先通过 dataSource 注入 | [] |
| openPicker | Function | 点击选择器后触发的选择函数,通常返回 FormDialog(...).open() 处理后的 option / option[] | - |
| cacheSelectedOptions | boolean | 是否缓存 openPicker 返回的 option,用于在 dataSource 未同步更新时优先展示 label | true |
| optionAsValue | boolean | 是否将 raw 原始选项作为字段值,而不是使用 value | false |
| valueKey | string | 完整值模式下从 raw 中提取内部返显值的字段名 | 'id' |
提示
openPicker返回的是一个对象PickerSelectOption而不直接是Field的值。如果开启了
cacheSelectedOptions则会缓存这些对象,Field的值是对象中的value属性;如果关闭了则自行加载相应的dataSource(如:还没有打开Dialog就已经有初始值的情况)。当字段当前值在
dataSource中找不到匹配项时,会回退显示对应的value。
PickerSelectOption
ts
interface PickerSelectOption {
label: string
value: any
disabled?: boolean
// 可扩展其他业务字段,组件内部不会读取
}插槽
组件继承 ElSelect 的常用展示插槽,第一版主要保留 prefix、empty、tag、loading、label 的原始能力,不额外扩展作用域协议。