FormGrid
FormGrid 组件
提示
在Vue中使用createFormGrid需要从FormGrid.createFormGrid中引入,它会返回一个markRaw的formGrid实例,没有markRaw的formGrid会引起shouldVisible等监听函数无限循环执行。
Markup Schema 案例
vue
<script setup lang="ts">
import { createForm } from '@formily/core'
import { createSchemaField, FormProvider } from '@formily/vue'
import { FormGrid, FormItem, Input, Submit } from '@silver-formily/element-plus'
const form = createForm()
const { SchemaField, SchemaVoidField, SchemaStringField } = createSchemaField({
components: {
FormItem,
Input,
FormGrid,
},
})
async function onSubmit(value) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaVoidField
x-component="FormGrid"
:x-component-props="{
maxColumns: 3,
minColumns: 2,
}"
>
<SchemaStringField
name="aaa"
title="aaa"
x-decorator="FormItem"
:x-decorator-props="{ 'data-grid-span': '2' }"
x-component="Input"
/>
<SchemaStringField
name="bbb"
title="bbb"
x-decorator="FormItem"
x-component="Input"
/>
<SchemaStringField
name="ccc"
title="ccc"
x-decorator="FormItem"
x-component="Input"
/>
<SchemaStringField
name="ddd"
title="ddd"
x-decorator="FormItem"
x-component="Input"
/>
<SchemaStringField
name="eee"
title="eee"
x-decorator="FormItem"
x-component="Input"
/>
<SchemaStringField
name="fff"
title="fff"
x-decorator="FormItem"
x-component="Input"
/>
<SchemaStringField
name="ggg"
title="ggg"
x-decorator="FormItem"
x-component="Input"
/>
</SchemaVoidField>
</SchemaField>
<Submit @submit="onSubmit">
提交
</Submit>
</FormProvider>
</template>JSON Schema 案例
vue
<script setup lang="ts">
import { createForm } from '@formily/core'
import { createSchemaField, FormProvider } from '@formily/vue'
import { FormGrid, FormItem, Input, Submit } from '@silver-formily/element-plus'
const schema = {
type: 'object',
properties: {
grid: {
'type': 'void',
'x-component': 'FormGrid',
'x-component-props': {
minColumns: [4, 6, 10],
},
'properties': {
aaa: {
'type': 'string',
'title': 'AAA',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
bbb: {
'type': 'string',
'title': 'BBB',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
ccc: {
'type': 'string',
'title': 'CCC',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
ddd: {
'type': 'string',
'title': 'DDD',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
eee: {
'type': 'string',
'title': 'EEE',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
fff: {
'type': 'string',
'title': 'FFF',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
ggg: {
'type': 'string',
'title': 'GGG',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
},
},
}
const form = createForm()
const { SchemaField } = createSchemaField({
components: {
FormItem,
Input,
FormGrid,
},
})
async function onSubmit(value) {
console.log(value)
}
</script>
<template>
<FormProvider :form="form">
<SchemaField :schema="schema" />
<Submit @submit="onSubmit">
提交
</Submit>
</FormProvider>
</template>原生案例
vue
<script setup lang="tsx">
import { FormGrid } from '@silver-formily/element-plus'
function Cell(_props, { slots }) {
return (
<div
style={{
backgroundColor: '#AAA',
color: '#FFF',
height: '30px',
display: 'flex',
alignItems: 'center',
padding: '0 10px',
}}
>
{slots?.default()}
</div>
)
}
const FormGridColumn = FormGrid.GridColumn
</script>
<template>
<div>
<p>maxColumns 3 + minColumns 2</p>
<FormGrid :max-columns="3" :min-columns="2" :column-gap="4">
<FormGridColumn :grid-span="4">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>maxColumns 3</p>
<FormGrid :max-columns="3" :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>minColumns 2</p>
<FormGrid :min-columns="2" :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>Null</p>
<FormGrid :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>minWidth 150 +maxColumns 3</p>
<FormGrid :min-width="150" :max-columns="3" :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>maxWidth 120+minColumns 2</p>
<FormGrid :max-width="120" :min-columns="2" :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>3</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>4</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>5</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>6</Cell>
</FormGridColumn>
</FormGrid>
<p>maxWidth 120 + gridSpan -1</p>
<FormGrid :max-width="120" :column-gap="4">
<FormGridColumn :grid-span="2">
<Cell>1</Cell>
</FormGridColumn>
<FormGridColumn>
<Cell>2</Cell>
</FormGridColumn>
<FormGridColumn :grid-span="-1">
<Cell>3</Cell>
</FormGridColumn>
</FormGrid>
</div>
</template>查询表单实现案例
vue
<script setup lang="tsx">
import { createForm } from '@formily/core'
import { Grid } from '@formily/grid'
import { autorun } from '@formily/reactive'
import { observer } from '@formily/reactive-vue'
import {
createSchemaField,
FormProvider,
FragmentComponent,
} from '@formily/vue'
import {
DatePicker,
Form,
FormButtonGroup,
FormGrid,
FormItem,
Input,
Reset,
Select,
Submit,
} from '@silver-formily/element-plus'
import { defineComponent, onUnmounted, ref } from 'vue'
function useCollapseGrid(maxRows) {
const grid = new Grid({
maxColumns: 4,
maxWidth: 240,
maxRows,
shouldVisible: (node, grid) => {
if (node.index === grid.childSize - 1)
return true
if (grid.maxRows === Infinity)
return true
return node.shadowRow < maxRows + 1
},
})
const expanded = ref(false)
const type = ref('')
const takeType = (realRows, computeRows) => {
if (realRows < maxRows + 1)
return 'incomplete-wrap'
if (computeRows > maxRows)
return 'collapsible'
return 'complete-wrap'
}
const dispose = autorun(() => {
expanded.value = grid.maxRows === Infinity
const realRows = grid.shadowRows
const computeRows = grid.fullnessLastColumn
? grid.shadowRows - 1
: grid.shadowRows
type.value = takeType(realRows, computeRows)
})
onUnmounted(dispose)
const toggle = () => {
grid.maxRows = grid.maxRows === Infinity ? maxRows : Infinity
}
return {
grid,
expanded,
toggle,
type,
}
}
const QueryForm = observer(
defineComponent({
setup(props, { slots }) {
const { grid, expanded, toggle, type } = useCollapseGrid(1)
const renderActions = () => {
return (
<FragmentComponent>
<Submit onSubmit={console.log}>查询</Submit>
<Reset>重置</Reset>
</FragmentComponent>
)
}
const renderButtonGroup = () => {
if (type.value === 'incomplete-wrap') {
return (
<FormButtonGroup.FormItem>
<FormButtonGroup>{renderActions()}</FormButtonGroup>
</FormButtonGroup.FormItem>
)
}
if (type.value === 'collapsible') {
return (
<FragmentComponent>
<FormButtonGroup>
<a
href=""
onClick={(e) => {
e.preventDefault()
toggle()
}}
>
{expanded.value ? '收起' : '展开'}
</a>
</FormButtonGroup>
<FormButtonGroup align="right">{renderActions()}</FormButtonGroup>
</FragmentComponent>
)
}
return (
<FormButtonGroup
align="right"
style={{ display: 'flex', width: '100%' }}
>
{renderActions()}
</FormButtonGroup>
)
}
return () => {
return (
<Form {...props} layout="vertical" feedbackLayout="terse">
<FormGrid grid={grid}>
{slots.default()}
<FormGrid.GridColumn
gridSpan={-1}
style={{ display: 'flex', justifyContent: 'space-between' }}
>
{renderButtonGroup()}
</FormGrid.GridColumn>
</FormGrid>
</Form>
)
}
},
}),
)
const form = createForm()
const { SchemaField, SchemaObjectField, SchemaStringField } = createSchemaField(
{
components: {
QueryForm,
Input,
Select,
DatePicker,
FormItem,
},
},
)
</script>
<template>
<FormProvider :form="form">
<SchemaField>
<SchemaObjectField x-component="QueryForm">
<SchemaStringField
name="input1"
title="Input 1"
x-component="Input"
x-decorator="FormItem"
/>
<SchemaStringField
name="input2"
title="Input 2"
x-component="Input"
x-decorator="FormItem"
/>
<SchemaStringField
name="select1"
title="Select 1"
x-component="Select"
x-decorator="FormItem"
/>
<SchemaStringField
name="select2"
title="Select 2"
x-component="Select"
x-decorator="FormItem"
/>
<SchemaStringField
name="date"
title="DatePicker"
x-component="DatePicker"
x-decorator="FormItem"
/>
<SchemaStringField
name="dateRange"
title="DatePicker"
x-component="DatePicker"
x-decorator="FormItem"
:x-decorator-props="{
gridSpan: 'span 2',
}"
:x-component-props="{
type: 'daterange',
}"
/>
<SchemaStringField
name="select3"
title="Select 3"
x-component="Select"
x-decorator="FormItem"
/>
</SchemaObjectField>
</SchemaField>
</FormProvider>
</template>API
FormGrid
| 属性名 | 类型 | 描述 | 默认值 |
|---|---|---|---|
| columnGap | number | 列间距 | 8 |
| rowGap | number | 行间距 | 4 |
| minColumns | number | number[] | 最小列数 | 0 |
| minWidth | number | number[] | 元素最小宽度 | 100 |
| maxColumns | number | number[] | 最大列数 | - |
| maxWidth | number | number[] | 元素最大宽度 | - |
| breakpoints | number[] | 容器尺寸断点 | [720, 1280, 1920] |
| colWrap | boolean | 自动换行 | true |
| strictAutoFit | boolean | GridItem 宽度是否严格受限于 maxWidth,不受限的话会自动占满容器 | false |
| shouldVisible | (node, grid) => boolean | 是否需要显示当前节点 | () => true |
| grid | Grid | 外部传入 Grid 实例,用于实现更复杂的布局逻辑 | - |
注意
minWidth的优先级高于minColumns。maxWidth的优先级高于maxColumns。minWidth/maxWidth/minColumns/maxColumns的数组格式与breakpoints数组一一映射。
FormGrid.GridColumn
| 属性名 | 类型 | 描述 | 默认值 |
|---|---|---|---|
| gridSpan | number | 元素所跨列数,如果为 -1,那么会自动反向跨列填补单元格 | 1 |
FormGrid.useFormGrid
从上下文中读取 Grid 实例
ts
interface useFormGrid {
(): Grid
}- Grid 实例属性方法参考 文档
FormGrid.createFormGrid
创建formGrid的实例,与直接使用不同的是它会返回一个 markRaw 的formGrid实例。避免循环触发事件。