PickerSelect
Popup-based select box
Template
Dialog Table Picker
<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,
}))
function openUserPicker({ field }) {
return FormDialog('Select Members', () => (
<Field
name="users"
component={[
SelectTable,
{
rowKey: 'id',
optionAsValue: true,
columns: [
{ prop: 'name', label: 'Name' },
{ prop: 'team', label: 'Team' },
],
},
]}
dataSource={userRows}
/>
))
.forOpen((form, next) => {
form.setValues({
users: userRows.filter(item => field?.value?.includes?.(item.id)),
})
next()
})
.open()
.then(values => values.users.map(item => ({
label: `${item.name} / ${item.team}`,
value: item.id,
raw: item,
})))
}
function log(value: any) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="users"
title="Members"
:decorator="[FormItem]"
:component="[
PickerSelect,
{
multiple: true,
clearable: true,
collapseTags: true,
collapseTagsTooltip: true,
openPicker: openUserPicker,
placeholder: 'Click to select members',
},
]"
:initial-value="['u1', 'u2', 'u3']"
:data-source="userOptions"
/>
<Submit style="margin-top: 16px" @submit="log">
Submit
</Submit>
</FormProvider>
</template>Members:
查看源码
Returning Full Option Values 5.2.0
With optionAsValue enabled, PickerSelect submits the raw records while the internal select still uses value for display.
<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,
}))
function openUserPicker({ field }) {
const selectedIds = Array.isArray(field?.value)
? field.value.map(item => typeof item === 'object' ? item.id : item)
: []
return FormDialog('Select members', () => (
<Field
name="users"
component={[
SelectTable,
{
rowKey: 'id',
optionAsValue: true,
columns: [
{ prop: 'name', label: 'Name' },
{ prop: 'team', label: 'Team' },
],
},
]}
dataSource={userRows}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({
users: userRows.filter(item => selectedIds.includes(item.id)),
})
next()
})
.open()
.then(values => values.users.map(item => ({
label: `${item.name} / ${item.team}`,
value: item.id,
raw: item,
})))
}
function log(value: any) {
console.log('Submitted full user records:', value)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="users"
title="Members"
:decorator="[FormItem]"
:component="[
PickerSelect,
{
multiple: true,
optionAsValue: true,
valueKey: 'id',
clearable: true,
collapseTags: true,
openPicker: openUserPicker,
placeholder: 'Select members and submit full records',
},
]"
:initial-value="userRows.slice(0, 2)"
:data-source="userOptions"
/>
<Submit style="margin-top: 16px" @submit="log">
Submit full records
</Submit>
</FormProvider>
</template>Members:
查看源码
- When
optionAsValueis enabled,Field.valuecontains the option'srawobject while the internal select still uses the option'svaluefor display. Returned options should providerawin full-value mode. - Use
valueKeywhen the raw record's identifier is notid.
Single-Selection Dialog
In single-selection mode, PickerSelect stores one string, number, or object instead of an array.
<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 }))
function openPicker({ field }) {
return FormDialog('Select owner', () => (
<Field
name="person"
component={[SelectTable, { mode: 'single', rowKey: 'id', showAlertToolbar: false, columns: [
{ prop: 'name', label: 'Name' },
{ prop: 'team', label: 'Team' },
] }]}
dataSource={people}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
.then((values) => {
const item = people.find(item => item.id === values.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="Owner"
:decorator="[FormItem]"
:component="[PickerSelect, { openPicker, clearable: true, placeholder: 'Select owner' }]"
:initial-value="102"
:data-source="options"
/>
<Submit style="margin-top: 16px" @submit="log">
Submit
</Submit>
</FormProvider>
</template>Owner:
查看源码
JSON Schema
Scalar value
<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 }))
function openPicker({ field }) {
return FormDialog('Select owner', () => <FieldDialog />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
.then((values) => {
const item = people.find(item => item.id === values.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: 'Name' }, { prop: 'team', label: 'Team' }] }]}
dataSource={people}
/>
)
}
const schema = { type: 'object', properties: { person: {
'type': 'string',
'title': 'Owner',
'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
</Submit>
</FormProvider>
</template>Owner:
查看源码
Full object 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 }))
function openPicker({ field }) {
return FormDialog('Select owner', () => (
<Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', optionAsValue: true, showAlertToolbar: false, columns: [{ prop: 'name', label: 'Name' }, { prop: 'team', label: 'Team' }] }]} dataSource={people} />
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: people.find(item => item.id === field?.value?.id) })
next()
})
.open()
.then(values => values.person && { label: values.person.name, value: values.person.id, raw: values.person })
}
const schema = { type: 'object', properties: { person: {
'type': 'object',
'title': 'Owner',
'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 full object
</Submit>
</FormProvider>
</template>Owner:
查看源码
Multiple selection
<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 }))
function openPicker({ field }) {
const selectedIds = Array.isArray(field?.value) ? field.value : []
return FormDialog('Select members', () => (
<Field
name="people"
component={[SelectTable, { mode: 'multiple', rowKey: 'id', optionAsValue: true, columns: [{ prop: 'name', label: 'Name' }, { prop: 'team', label: 'Team' }] }]}
dataSource={people}
/>
))
.forOpen((dialogForm, next) => {
dialogForm.setValues({ people: people.filter(item => selectedIds.includes(item.id)) })
next()
})
.open()
.then(values => values.people.map(item => ({ label: item.name, value: item.id, raw: item })))
}
const schema = { type: 'object', properties: { people: {
'type': 'array',
'title': 'Members',
'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
</Submit>
</FormProvider>
</template>Members:
查看源码
Markup Schema
Scalar value
<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 }))
function openPicker({ field }) {
return FormDialog('Select owner', () => <Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', showAlertToolbar: false, columns: [{ prop: 'name', label: 'Name' }, { prop: 'team', label: 'Team' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: field?.value })
next()
})
.open()
.then((values) => {
const item = people.find(item => item.id === values.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="Owner" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ openPicker, clearable: true }" :enum="options" :default="102" /></SchemaField>
<Submit @submit="log">
Submit
</Submit>
</FormProvider>
</template>Owner:
查看源码
Full object 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 }))
function openPicker({ field }) {
return FormDialog('Select owner', () => <Field name="person" component={[SelectTable, { mode: 'single', rowKey: 'id', optionAsValue: true, showAlertToolbar: false, columns: [{ prop: 'name', label: 'Name' }, { prop: 'team', label: 'Team' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ person: people.find(item => item.id === field?.value?.id) })
next()
})
.open()
.then(values => values.person && { label: values.person.name, value: values.person.id, raw: values.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="Owner" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ optionAsValue: true, valueKey: 'id', openPicker }" :enum="options" :default="people[1]" /></SchemaField>
<Submit @submit="log">
Submit full object
</Submit>
</FormProvider>
</template>Owner:
查看源码
Multiple selection
<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 }))
function openPicker({ field }) {
const selectedIds = Array.isArray(field?.value) ? field.value : []
return FormDialog('Select members', () => <Field name="people" component={[SelectTable, { mode: 'multiple', rowKey: 'id', optionAsValue: true, columns: [{ prop: 'name', label: 'Name' }, { prop: 'team', label: 'Team' }] }]} dataSource={people} />)
.forOpen((dialogForm, next) => {
dialogForm.setValues({ people: people.filter(item => selectedIds.includes(item.id)) })
next()
})
.open()
.then(values => values.people.map(item => ({ label: item.name, value: item.id, raw: item })))
}
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="Members" x-decorator="FormItem" x-component="PickerSelect" :x-component-props="{ multiple: true, openPicker, collapseTags: true }" :enum="options" :default="['u1', 'u2']" /></SchemaField>
<Submit @submit="log">
Submit
</Submit>
</FormProvider>
</template>Members:
查看源码
API
See https://element-plus.org/en-US/component/select.html
Extended Props
| Prop | Type | Description | Default |
|---|---|---|---|
options | PickerSelectOption[] | Candidate option list. In most cases, prefer injecting it through dataSource. | [] |
openPicker | Function | Picker function triggered when the selector is clicked. Usually returns the option or options returned by FormDialog(...).open(). | - |
cacheSelectedOptions | boolean | Whether to cache options returned by openPicker so labels can be displayed before dataSource catches up. | true |
optionAsValue | boolean | Whether to use the option's raw object as the field value instead of value. | false |
valueKey | string | The field in raw used to recover the internal display value in full-value mode. | 'id' |
Tip
openPickerreturns a PickerSelectOption object instead of the rawFieldvalue.- When
cacheSelectedOptionsis enabled, those option objects are cached andField.valueis taken from theirvaluefield. When disabled, you need to load the correspondingdataSourceyourself, for example when an initial value exists before the dialog is opened. - When the current field value cannot be matched in
dataSource, the component falls back to displaying the rawvalue.
PickerSelectOption
ts
interface PickerSelectOption {
label: string
value: any
disabled?: boolean
// Extend with other business fields. The component does not read them internally.
}Slots
The component inherits the common display slots from ElSelect. The first version mainly keeps the original behavior of prefix, empty, tag, loading, and label, without adding extra scope protocol.