Skip to content

Commit

Permalink
feat: add formitem demo
Browse files Browse the repository at this point in the history
  • Loading branch information
quirkyshop committed Feb 14, 2021
1 parent 8b23b8e commit 5a263e6
Show file tree
Hide file tree
Showing 4 changed files with 397 additions and 3 deletions.
172 changes: 172 additions & 0 deletions packages/antd/docs/components/FormItem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
# FormItem

> 表单字段组件,用于展示布局。
## Markup Schema 案例

```tsx
import React from 'react'
import { Form, Input as NextInput, Select } from 'antd';
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
components: {
Input,
Select,
FormItem,
},
})

const form = createForm()

export default () => (
<FormProvider form={form}>
<SchemaField>
<SchemaField.String
name="input"
title="输入框输入框输入框"
x-decorator="FormItem"
x-component="Input"
required
// description="description"
x-decorator-props={{
// help: 'help',
extra: 'extra',
labelWidth: 100,
addonBefore: 'addonBefore',
addonAfter: 'addonAfter',
}}
/>
<SchemaField.String
name="select"
title="下拉框"
x-decorator="FormItem"
x-component="Select"
required
// description="description"
x-decorator-props={{
// help: 'help',
fullness: true,
extra: 'extra',
}}
/>
</SchemaField>
<FormButtonGroup>
<Submit onSubmit={console.log}>提交</Submit>
</FormButtonGroup>
<Form.Item labelCol={4} validateStatus="error" label="hello" help="help" extra="extra">
<NextInput />
</Form.Item>
</FormProvider>
)
```

## JOSN Schema 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, createSchemaField } from '@formily/react'

const SchemaField = createSchemaField({
components: {
Input,
FormItem,
},
})

const form = createForm()

const schema = {
type: 'object',
properties: {
input: {
type: 'string',
title: '输入框',
'x-decorator': 'FormItem',
'x-component': 'Input',
'x-component-props': {
style: {
width: 240,
},
},
},
},
}

export default () => (
<FormProvider form={form}>
<SchemaField schema={schema} />
<FormButtonGroup>
<Submit onSubmit={console.log}>提交</Submit>
</FormButtonGroup>
</FormProvider>
)
```

## 纯 JSX 案例

```tsx
import React from 'react'
import { Input, FormItem, FormButtonGroup, Submit } from '@formily/antd'
import { createForm } from '@formily/core'
import { FormProvider, Field } from '@formily/react'

const form = createForm()

export default () => (
<FormProvider form={form}>
<Field
name="input"
title="输入框"
required
decorator={[FormItem]}
component={[
Input,
{
style: {
width: 240,
},
},
]}
/>
<FormButtonGroup>
<Submit onSubmit={console.log}>提交</Submit>
</FormButtonGroup>
</FormProvider>
)
```

## API

### FormItem

| 属性名 | 类型 | 描述 | 默认值 |
| ------ | ------ | ---------- | ------ |
| colon | boolean | 冒号 | true |
| tooltip | ReactNode | 问号提示 | - |
| labelAlign | `"left"` \| `"right"` | 标签文本对齐方式 | `"right"` |
| labelWrap | boolean | 标签换⾏,否则出现省略号,hover有tooltip | false |
| labelWidth | number | 标签固定宽度 | - |
| wrapperWidth | number | 内容固定宽度 | - |
| labelCol | number | 标签⽹格所占列数,和内容列数加起来总和为24 | - |
| wrapperCol | number | 内容⽹格所占列数,和标签列数加起来总和为24 | - |
| wrapperAlign | `"left"` \| `"right"` | 内容文本对齐方式⻬ | `"left"` |
| wrapperWrap | boolean | 内容换⾏,否则出现省略号,hover有tooltip | false |
| fullness | boolean | 内容撑满 | false |
| addonBefore | ReactNode | 前缀内容 | - |
| addonAfter | ReactNode | 后缀内容 | - |
| size | `"small"` \| `"default"` \| `"large"` | 尺⼨ | - |
| inset | boolean | 是否是内嵌布局 | false |
| extra | ReactNode | 扩展描述⽂案 | - |
| feedbackText | ReactNode | 反馈⽂案 | - |
| feedbackLayout | `"loose"` \| `"terse"` \| `"popover"` | 反馈布局 | - |
| feedbackStatus | `"error"` \| `"warning"` \| `"success"` \| `"pending"` | 反馈布局 | - |
| feedbackIcon | ReactNode | 反馈图标 | - |
| asterisk | boolean | 星号提醒 | - |
| gridSpan | number | ⽹格布局占宽 | - |
| bordered | boolean | 是否有边框 | - |

98 changes: 96 additions & 2 deletions packages/antd/src/form-item/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,100 @@
import { Form } from 'antd'
import React from 'react'
import cls from 'classnames'
import { usePrefixCls } from '../__builtins__'
import { isVoidField } from '@formily/core'
import { connect, mapProps } from '@formily/react'
import { useFormLayout, useFormShallowLayout } from '../form-layout'

const useFormItemLayout = (props) => {
const shallowFormLayout = useFormShallowLayout();
const formLayout = useFormLayout();
const layout = shallowFormLayout || formLayout || {};

return {
...props,
colon: props.colon || layout.colon,
labelAlign: props.labelAlign || layout.labelAlign,
labelWrap: props.labelWrap || layout.labelWrap,
labelWidth: props.labelWidth || layout.labelWidth,
wrapperWidth: props.wrapperWidth || layout.wrapperWidth,
labelCol: props.labelCol || layout.labelCol,
wrapperCol: props.wrapperCol || layout.wrapperCol,
wrapperAlign: props.wrapperAlign || layout.wrapperAlign,
wrapperWrap: props.wrapperWrap || layout.wrapperWrap,
fullness: props.fullness || layout.fullness,
size: props.size || layout.size,
inset: props.inset || layout.inset,
asterisk: props.asterisk || layout.asterisk,
bordered: props.bordered || layout.bordered,
feedbackIcon: props.feedbackIcon || layout.feedbackIcon,
}
}

export const FormItemBase = (props) => {
const { children, ...others } = props;
const formLayout = useFormItemLayout(others);
const { label, colon = true, addonBefore, asterisk, feedbackStatus, extra, help,
fullness, feedbackLayout,
labelWidth, wrapperWidth, labelCol, wrapperCol,
labelAlign = 'right', wrapperAlign = 'left',
size, labelWrap, wrapperWrap,
} = formLayout;
const labelStyle: any = {};
const wrapperStyle: any = {};

// 固定宽度
let enableCol = false;
if (labelWidth || wrapperWidth) {
if (labelWidth) {
labelStyle.width = `${labelWidth}px`;
}
if (wrapperWidth) {
wrapperStyle.width = `${wrapperWidth}px`;
}
// 栅格模式
} else if (labelCol || wrapperCol) {
enableCol = true;
}

const prefixCls = usePrefixCls('formily-form-item', props)
return <div className={cls({
[`${prefixCls}`]: true,
[`${prefixCls}-${feedbackStatus}`]: !!feedbackStatus,
[`${prefixCls}-size-${size}`]: !!size,
[`${prefixCls}-feedback-layout-${feedbackLayout}`]: !!feedbackLayout,
[`${prefixCls}-fullness`]: !!fullness,
[`${prefixCls}-label-align-${labelAlign}`]: true,
[`${prefixCls}-control-align-${wrapperAlign}`]: true,
[`${prefixCls}-label-wrap`]: !!labelWrap,
[`${prefixCls}-control-wrap`]: !!wrapperWrap,
[`${prefixCls}-label-col-${labelCol}`]: enableCol && !!labelCol,
[`${prefixCls}-control-col-${wrapperCol}`]: enableCol && !!wrapperCol,
[props.className]: !!props.className,
})}>
<div className={cls(`${prefixCls}-label`)} style={labelStyle}>
{ asterisk && <span className={cls(`${prefixCls}-asterisk`)}>{'*'}</span>}
{label}
{ colon && <span className={cls(`${prefixCls}-colon`)}>{':'}</span> }
</div>
<div className={cls(`${prefixCls}-control`)} style={wrapperStyle}>
<div className={cls(`${prefixCls}-control-content`)}>
{addonBefore && <div className={cls(`${prefixCls}-addon-before`)}>{addonBefore}</div>}
<div className={cls(`${prefixCls}-control-content-component`)}>{children}</div>
{addonBefore && <div className={cls(`${prefixCls}-addon-after`)}>{addonBefore}</div>}
</div>
{help && <div className={cls(`${prefixCls}-help`)}>{help}</div>}
{extra && <div className={cls(`${prefixCls}-extra`)}>{extra}</div>}
</div>
</div>
}

export const FormItem = connect(
Form.Item,
FormItemBase,
mapProps(
{ extract: 'validateStatus' },
{ extract: 'title', to: 'label' },
{ extract: 'required' },
{ extract: 'required', to: 'asterisk' },
(props, field) => {
if (!field) return props
if (isVoidField(field)) return props
Expand All @@ -20,6 +107,13 @@ export const FormItem = connect(
help: field.description,
}
}
},
(props, field) => {
if (!field.feedbackStatus && field.validateStatus) {
return {
feedbackStatus: field.validateStatus,
}
}
}
)
)
Expand Down
Loading

0 comments on commit 5a263e6

Please sign in to comment.