Editable
Partial editor for form areas with tighter space requirements.
Editable is essentially a FormItem variant, so it is usually placed on the decorator side.
Note
In readPretty mode, Formily validation cannot be triggered directly. Because of that, this component library does not use the official mapReadPretty for read-pretty mappings. Instead, it uses an internally modified version that additionally reads readPretty from Field.data. When that value is true, the component still renders in read-pretty mode. This simulated read-pretty mode does not block Formily validation. If you build custom components that need to work with Editable, import mapReadPretty from @silver-formily/element-plus/__builtins__; otherwise read-pretty rendering will not work correctly.
Tip
Starting from @formily/core v2.3.3, validation-trigger states can be configured. If you use version 2.3.3 or above, you can use that capability together with the built-in mapReadPretty and still keep validation enabled.
Tip
When Editable switches modes, it no longer changes Field.pattern. Instead, it updates readPretty on Field.data, for the reasons explained above.
Markup Schema Example
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import {
DatePicker,
Editable,
FormButtonGroup,
FormItem,
Input,
Submit,
} from '@silver-formily/element-plus'
import { createSchemaField, FormProvider } from '@silver-formily/vue'
const { SchemaField, SchemaStringField, SchemaVoidField, SchemaObjectField }
= createSchemaField({
components: {
FormItem,
Input,
DatePicker,
Editable,
},
})
const form = createForm()
async function log(values: Record<string, any>) {
console.log(values)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaStringField
name="date"
title="Date"
x-decorator="Editable"
x-component="DatePicker"
/>
<SchemaStringField
name="input"
title="Input"
x-decorator="Editable"
x-component="Input"
/>
<SchemaVoidField
name="void"
title="Virtual Node Container"
x-component="Editable.Popover"
:x-reactions="
(field) => {
field.title = field.query('.void.date2').get('value') || field.title
}
"
>
<SchemaStringField
name="date2"
title="Date"
x-decorator="FormItem"
x-component="DatePicker"
/>
<SchemaStringField
name="input2"
title="Input"
x-decorator="FormItem"
x-component="Input"
/>
</SchemaVoidField>
<SchemaObjectField
name="object"
title="Object Node Container"
x-component="Editable.Popover"
:x-reactions="
(field) => {
field.title = (field.value && field.value.date) || field.title
}
"
>
<SchemaStringField
name="date"
title="Date"
x-decorator="FormItem"
x-component="DatePicker"
/>
<SchemaStringField
name="input"
title="Input"
x-decorator="FormItem"
x-component="Input"
/>
</SchemaObjectField>
</SchemaField>
<FormButtonGroup>
<Submit @submit="log">
Submit
</Submit>
</FormButtonGroup>
</FormProvider>
</template>
<style lang="scss" scoped></style>JSON Schema Example
Use the
editPropsprop to control size and other props in edit mode.
<script lang="ts" setup>
import { createForm } from '@silver-formily/core'
import {
DatePicker,
Editable,
FormButtonGroup,
FormItem,
Input,
Submit,
} from '@silver-formily/element-plus'
import { createSchemaField, FormProvider } from '@silver-formily/vue'
const { SchemaField } = createSchemaField({
components: {
FormItem,
Input,
DatePicker,
Editable,
},
})
const schema = {
type: 'object',
properties: {
date: {
'type': 'string',
'title': 'Date',
'x-decorator': 'Editable',
'x-decorator-props': {
editProps: {
size: 'small',
class: 'editable-date-picker__width',
},
},
'x-component': 'DatePicker',
'x-component-props': {
type: 'daterange',
},
},
input: {
'type': 'string',
'title': 'Input',
'x-decorator': 'Editable',
'x-decorator-props': {
editProps: {
size: 'small',
style: {
width: '80px',
},
},
},
'x-component': 'Input',
},
void: {
'type': 'void',
'title': 'Virtual Node Container',
'x-component': 'Editable.Popover',
'x-reactions':
'{{(field) => field.title = field.query(\'.void.date2\').get(\'value\') || field.title}}',
'properties': {
date2: {
'type': 'string',
'title': 'Date',
'x-decorator': 'FormItem',
'x-component': 'DatePicker',
},
input2: {
'type': 'string',
'title': 'Input',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
iobject: {
'type': 'object',
'title': 'Object Node Container',
'x-component': 'Editable.Popover',
'x-reactions':
'{{(field) => field.title = field.value && field.value.date || field.title}}',
'properties': {
date: {
'type': 'string',
'title': 'Date',
'x-decorator': 'FormItem',
'x-component': 'DatePicker',
},
input: {
'type': 'string',
'title': 'Input',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
},
}
const form = createForm()
async function log(values: Record<string, any>) {
console.log(values)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" />
<FormButtonGroup>
<Submit @submit="log">
Submit
</Submit>
</FormButtonGroup>
</FormProvider>
</template>
<style lang="scss">
.editable-date-picker__width .el-tooltip__trigger {
--el-date-editor-daterange-width: 200px;
}
</style>Template Example
<script lang="ts" setup>
import { createForm, isField } from '@silver-formily/core'
import {
DatePicker,
Editable,
FormButtonGroup,
FormItem,
Input,
Submit,
} from '@silver-formily/element-plus'
import { Field, FormProvider, ObjectField, VoidField } from '@silver-formily/vue'
const form = createForm()
async function log(values: Record<string, any>) {
console.log(values)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="date"
title="Date"
:decorator="[Editable]"
:component="[DatePicker]"
/>
<Field
name="input"
title="Input"
:decorator="[Editable]"
:component="[Input]"
/>
<VoidField
name="void"
title="Virtual Node Container"
:component="[Editable.Popover]"
:reactions="
(field) => {
field.title = field.query('.void.date2').get('value') || field.title
}
"
>
<Field
name="date2"
title="Date"
:decorator="[FormItem]"
:component="[DatePicker]"
/>
<Field
name="input2"
title="Input"
:decorator="[FormItem]"
:component="[Input]"
/>
</VoidField>
<ObjectField
name="iobject"
title="Object Node Container"
:component="[Editable.Popover]"
:reactions="
(field) => {
isField(field)
&& (field.title = (field.value && field.value.date) || field.title)
}
"
>
<Field
name="date"
title="Date"
:decorator="[FormItem]"
:component="[DatePicker]"
/>
<Field
name="input"
title="Input"
:decorator="[FormItem]"
:component="[Input]"
/>
</ObjectField>
<Field
name="disabled"
title="Disabled"
:decorator="[Editable]"
:component="[Input]"
initial-value="Disabled Editable"
:disabled="true"
/>
<FormButtonGroup>
<Submit @submit="log">
Submit
</Submit>
</FormButtonGroup>
</FormProvider>
</template>
<style lang="scss" scoped></style>Template Validation Example
<script lang="ts" setup>
import { createForm, isField } from '@silver-formily/core'
import {
DatePicker,
Editable,
FormButtonGroup,
FormItem,
Input,
Submit,
} from '@silver-formily/element-plus'
import { Field, FormProvider, ObjectField, VoidField } from '@silver-formily/vue'
const form = createForm()
async function log(values: Record<string, any>) {
console.log(values)
}
</script>
<template>
<FormProvider :form="form">
<Field
name="input"
title="Input"
:decorator="[Editable]"
:component="[Input]"
validator="email"
/>
<VoidField
name="void"
title="Virtual Node Container"
:component="[Editable.Popover]"
:reactions="
(field) => {
field.title = field.query('.void.date2').get('value') || field.title
}
"
>
<Field
name="date2"
title="Date"
:decorator="[FormItem]"
:component="[DatePicker]"
/>
<Field
name="input2"
title="Input"
:decorator="[FormItem]"
:component="[Input]"
validator="email"
/>
</VoidField>
<ObjectField
name="iobject"
title="Object Node Container"
:component="[Editable.Popover]"
:reactions="
(field) => {
isField(field)
&& (field.title = (field.value && field.value.date) || field.title)
}
"
>
<Field
name="date"
title="Date"
:decorator="[FormItem]"
:component="[DatePicker]"
/>
<Field
name="input"
title="Input"
:decorator="[FormItem]"
:component="[Input]"
:validator="[{ required: true }, 'email']"
/>
</ObjectField>
<FormButtonGroup>
<Submit @submit="log">
Submit
</Submit>
</FormButtonGroup>
</FormProvider>
</template>
<style lang="scss" scoped></style>API
Editable
Inline editing
See /en/component/form-item.html#api
| Prop | Description | Type | Default |
|---|---|---|---|
editProps | Extra props applied while in edit mode | object | null |
Editable.Popover
Popover editing
See /en/component/form-item.html#api
See https://element-plus.org/en-US/component/popover.html
Editable.Popover supports all props from both FormItem and ElPopover. There should be no conflicts between them; if one does appear, FormItem props currently take precedence. Slots from the two components are not supported for now.