Skip to content

Commit

Permalink
docs: Update batch of docs & demos (ant-design#44509)
Browse files Browse the repository at this point in the history
* docs: update select opt

* docs: update form deps demo

* docs: upload onChange

* docs: update form nest Form.List demo
  • Loading branch information
zombieJ committed Aug 29, 2023
1 parent 9c494ab commit 8d7dd80
Show file tree
Hide file tree
Showing 15 changed files with 622 additions and 475 deletions.
455 changes: 243 additions & 212 deletions components/form/__tests__/__snapshots__/demo-extend.test.ts.snap

Large diffs are not rendered by default.

371 changes: 238 additions & 133 deletions components/form/__tests__/__snapshots__/demo.test.tsx.snap

Large diffs are not rendered by default.

7 changes: 0 additions & 7 deletions components/form/demo/dep-debug.md

This file was deleted.

31 changes: 0 additions & 31 deletions components/form/demo/dep-debug.tsx

This file was deleted.

7 changes: 7 additions & 0 deletions components/form/demo/dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## zh-CN

Form.Item 可以通过 `dependencies` 属性,设置关联字段。当关联字段的值发生变化时,会触发校验与更新。

## en-US

Form.Item can set the associated field through the `dependencies` property. When the value of the associated field changes, the validation and update will be triggered.
57 changes: 57 additions & 0 deletions components/form/demo/dependencies.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { Alert, Form, Input, Typography } from 'antd';

const App: React.FC = () => {
const [form] = Form.useForm();
return (
<Form
form={form}
name="dependencies"
autoComplete="off"
style={{ maxWidth: 600 }}
layout="vertical"
>
<Alert message=" Try modify `Password2` and then modify `Password`" type="info" showIcon />

<Form.Item label="Password" name="password" rules={[{ required: true }]}>
<Input />
</Form.Item>

{/* Field */}
<Form.Item
label="Confirm Password"
name="password2"
dependencies={['password']}
rules={[
{
required: true,
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error('The new password that you entered do not match!'));
},
}),
]}
>
<Input />
</Form.Item>

{/* Render Props */}
<Form.Item noStyle dependencies={['password2']}>
{() => (
<Typography>
<p>
Only Update when <code>password2</code> updated:
</p>
<pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre>
</Typography>
)}
</Form.Item>
</Form>
);
};

export default App;
4 changes: 2 additions & 2 deletions components/form/demo/dynamic-form-items-complex.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## zh-CN

这个例子演示了一个表单中包含多个表单控件的情况
多个 Form.List 嵌套的使用场景

## en-US

This example demonstrates the case that a form contains multiple form controls.
Multiple Form.List nested usage scenarios.
131 changes: 59 additions & 72 deletions components/form/demo/dynamic-form-items-complex.tsx
Original file line number Diff line number Diff line change
@@ -1,96 +1,83 @@
import React from 'react';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Form, Input, Select, Space } from 'antd';

const { Option } = Select;

const areas = [
{ label: 'Beijing', value: 'Beijing' },
{ label: 'Shanghai', value: 'Shanghai' },
];

const sights = {
Beijing: ['Tiananmen', 'Great Wall'],
Shanghai: ['Oriental Pearl', 'The Bund'],
};

type SightsKeys = keyof typeof sights;
import { CloseOutlined } from '@ant-design/icons';
import { Button, Card, Form, Input, Space, Typography } from 'antd';

const App: React.FC = () => {
const [form] = Form.useForm();

const onFinish = (values: any) => {
console.log('Received values of form:', values);
};

const handleChange = () => {
form.setFieldsValue({ sights: [] });
};

return (
<Form
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
form={form}
name="dynamic_form_complex"
onFinish={onFinish}
style={{ maxWidth: 600 }}
autoComplete="off"
initialValues={{ items: [{}] }}
>
<Form.Item name="area" label="Area" rules={[{ required: true, message: 'Missing area' }]}>
<Select options={areas} onChange={handleChange} />
</Form.Item>
<Form.List name="sights">
<Form.List name="items">
{(fields, { add, remove }) => (
<>
<div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}>
{fields.map((field) => (
<Space key={field.key} align="baseline">
<Form.Item
noStyle
shouldUpdate={(prevValues, curValues) =>
prevValues.area !== curValues.area || prevValues.sights !== curValues.sights
}
>
{() => (
<Form.Item
{...field}
label="Sight"
name={[field.name, 'sight']}
rules={[{ required: true, message: 'Missing sight' }]}
>
<Select disabled={!form.getFieldValue('area')} style={{ width: 130 }}>
{(sights[form.getFieldValue('area') as SightsKeys] || []).map((item) => (
<Option key={item} value={item}>
{item}
</Option>
))}
</Select>
</Form.Item>
)}
</Form.Item>
<Form.Item
{...field}
label="Price"
name={[field.name, 'price']}
rules={[{ required: true, message: 'Missing price' }]}
>
<Card
size="small"
title={`Item ${field.name + 1}`}
key={field.key}
extra={
<CloseOutlined
onClick={() => {
remove(field.name);
}}
/>
}
>
<Form.Item label="Name" name={[field.name, 'name']}>
<Input />
</Form.Item>

<MinusCircleOutlined onClick={() => remove(field.name)} />
</Space>
{/* Nest Form.List */}
<Form.Item label="List">
<Form.List name={[field.name, 'list']}>
{(subFields, subOpt) => (
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 16 }}>
{subFields.map((subField) => (
<Space key={subField.key}>
<Form.Item noStyle name={[subField.name, 'first']}>
<Input placeholder="first" />
</Form.Item>
<Form.Item noStyle name={[subField.name, 'second']}>
<Input placeholder="second" />
</Form.Item>
<CloseOutlined
onClick={() => {
subOpt.remove(subField.name);
}}
/>
</Space>
))}
<Button type="dashed" onClick={() => subOpt.add()} block>
+ Add Sub Item
</Button>
</div>
)}
</Form.List>
</Form.Item>
</Card>
))}

<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
Add sights
</Button>
</Form.Item>
</>
<Button type="dashed" onClick={() => add()} block>
+ Add Item
</Button>
</div>
)}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>

<Form.Item noStyle shouldUpdate>
{() => (
<Typography>
<pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre>
</Typography>
)}
</Form.Item>
</Form>
);
Expand Down
6 changes: 2 additions & 4 deletions components/form/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ High performance Form component with data scope management. Including data colle
<code src="./demo/without-form-create.tsx">Handle Form Data Manually</code>
<code src="./demo/validate-static.tsx">Customized Validation</code>
<code src="./demo/dynamic-rule.tsx">Dynamic Rules</code>
<code src="./demo/dependencies.tsx">Dependencies</code>
<code src="./demo/validate-other.tsx">Other Form Controls</code>
<code src="./demo/disabled-input-debug.tsx" debug>Disabled Input Debug</code>
<code src="./demo/dep-debug.tsx" debug>Dep Debug</code>
<code src="./demo/label-debug.tsx" debug>label ellipsis</code>
<code src="./demo/col-24-debug.tsx" debug>Test col 24 usage</code>
<code src="./demo/ref-item.tsx" debug>Ref item</code>
Expand Down Expand Up @@ -153,12 +153,10 @@ After wrapped by `Form.Item` with `name` property, `value`(or other property def

### dependencies

Used when there are dependencies between fields. If a field has the `dependencies` prop, this field will automatically trigger updates and validations when upstream is updated. A common scenario is a user registration form with "password" and "confirm password" fields. The "Confirm Password" validation depends on the "Password" field. After setting `dependencies`, the "Password" field update will re-trigger the validation of "Check Password". You can refer [examples](#components-form-demo-register).
Used when there are dependencies between fields. If a field has the `dependencies` prop, this field will automatically trigger updates and validations when upstream is updated. A common scenario is a user registration form with "password" and "confirm password" fields. The "Confirm Password" validation depends on the "Password" field. After setting `dependencies`, the "Password" field update will re-trigger the validation of "Check Password". You can refer [examples](#components-form-demo-dependencies).

`dependencies` shouldn't be used together with `shouldUpdate`, since it may result in conflicting update logic.

`dependencies` supports `Form.Item` with render props children since `4.5.0`.

### shouldUpdate

Form updates only the modified field-related components for performance optimization purposes by incremental update. In most cases, you only need to write code or do validation with the [`dependencies`](#dependencies) property. In some specific cases, such as when a new field option appears with a field value changed, or you just want to keep some area updating by form update, you can modify the update logic of Form.Item via the `shouldUpdate`.
Expand Down
6 changes: 2 additions & 4 deletions components/form/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*ylFATY6w-ygAAA
<code src="./demo/without-form-create.tsx">自行处理表单数据</code>
<code src="./demo/validate-static.tsx">自定义校验</code>
<code src="./demo/dynamic-rule.tsx">动态校验规则</code>
<code src="./demo/dependencies.tsx">校验与更新依赖</code>
<code src="./demo/validate-other.tsx">校验其他组件</code>
<code src="./demo/disabled-input-debug.tsx" debug>Disabled Input Debug</code>
<code src="./demo/dep-debug.tsx" debug>Dep Debug</code>
<code src="./demo/label-debug.tsx" debug>测试 label 省略</code>
<code src="./demo/col-24-debug.tsx" debug>测试特殊 col 24 用法</code>
<code src="./demo/ref-item.tsx" debug>引用字段</code>
Expand Down Expand Up @@ -154,12 +154,10 @@ const validateMessages = {

### dependencies

当字段间存在依赖关系时使用。如果一个字段设置了 `dependencies` 属性。那么它所依赖的字段更新时,该字段将自动触发更新与校验。一种常见的场景,就是注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段,设置 `dependencies` 后,“密码”字段更新会重新触发“校验密码”的校验逻辑。你可以参考[具体例子](#components-form-demo-register)
当字段间存在依赖关系时使用。如果一个字段设置了 `dependencies` 属性。那么它所依赖的字段更新时,该字段将自动触发更新与校验。一种常见的场景,就是注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段,设置 `dependencies` 后,“密码”字段更新会重新触发“校验密码”的校验逻辑。你可以参考[具体例子](#components-form-demo-dependencies)

`dependencies` 不应和 `shouldUpdate` 一起使用,因为这可能带来更新逻辑的混乱。

`4.5.0` 版本开始,`dependencies` 支持使用 render props 类型 children 的 `Form.Item`

### shouldUpdate

Form 通过增量更新方式,只更新被修改的字段相关组件以达到性能优化目的。大部分场景下,你只需要编写代码或者与 [`dependencies`](#dependencies) 属性配合校验即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都对某一个区域进行渲染。你可以通过 `shouldUpdate` 修改 Form.Item 的更新逻辑。
Expand Down
8 changes: 5 additions & 3 deletions components/select/demo/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ const onSearch = (value: string) => {
console.log('search:', value);
};

// Filter `option.label` match the user type `input`
const filterOption = (input: string, option: { label: string; value: string }) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase());

const App: React.FC = () => (
<Select
showSearch
placeholder="Select a person"
optionFilterProp="children"
onChange={onChange}
onSearch={onSearch}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
filterOption={filterOption}
options={[
{
value: 'jack',
Expand Down
4 changes: 2 additions & 2 deletions components/select/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Select component to select value from options.

- A dropdown menu for displaying choices - an elegant alternative to the native `<select>` element.
- Utilizing [Radio](/components/radio/) is recommended when there are fewer total options (less than 5).
- You probably need [AutoComplete](/components/auto-complete/) if you're looking for an input box that can be typed or selected.
- You probably need [AutoComplete](/components/auto-complete/) if you're looking for an input box that can be typed or selected.

## Examples

Expand Down Expand Up @@ -69,7 +69,7 @@ Common props ref:[Common props](/docs/react/common-props)
| dropdownRender | Customize dropdown content | (originNode: ReactNode) => ReactNode | - | |
| dropdownStyle | The style of dropdown menu | CSSProperties | - | |
| fieldNames | Customize node label, value, options,groupLabel field name | object | { label: `label`, value: `value`, options: `options`, groupLabel: `label` } | 4.17.0 (`groupLabel` added in 5.6.0) |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded | boolean \| function(inputValue, option) | true | |
| filterOption | If true, filter options by input, if function, filter options against it. The function will receive two arguments, `inputValue` and `option`, if the function returns `true`, the option will be included in the filtered set; Otherwise, it will be excluded. [Example](#select-demo-search) | boolean \| function(inputValue, option) | true | |
| filterSort | Sort function for search options sorting, see [Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)'s compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
| getPopupContainer | Parent Node which the selector should be rendered to. Default to `body`. When position issues happen, try to modify it into scrollable content and position it relative. [Example](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
| labelInValue | Whether to embed label in value, turn the format of value from `string` to { value: string, label: ReactNode } | boolean | false | |
Expand Down
2 changes: 1 addition & 1 deletion components/select/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ demo:
| dropdownRender | 自定义下拉框内容 | (originNode: ReactNode) => ReactNode | - | |
| dropdownStyle | 下拉菜单的 style 属性 | CSSProperties | - | |
| fieldNames | 自定义节点 label、value、options、groupLabel 的字段 | object | { label: `label`, value: `value`, options: `options`, groupLabel: `label` } | 4.17.0(`groupLabel` 在 5.6.0 新增) |
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false | boolean \| function(inputValue, option) | true | |
| filterOption | 是否根据输入项进行筛选。当其为一个函数时,会接收 `inputValue` `option` 两个参数,当 `option` 符合筛选条件时,应返回 true,反之则返回 false[示例](#select-demo-search) | boolean \| function(inputValue, option) | true | |
| filterSort | 搜索时对筛选结果项的排序函数, 类似[Array.sort](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)里的 compareFunction | (optionA: Option, optionB: Option) => number | - | 4.9.0 |
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。[示例](https://codesandbox.io/s/4j168r7jw0) | function(triggerNode) | () => document.body | |
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 { value: string, label: ReactNode } 的格式 | boolean | false | |
Expand Down
4 changes: 2 additions & 2 deletions components/upload/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ Common props ref:[Common props](/docs/react/common-props)
| progress | Custom progress bar | [ProgressProps](/components/progress/#api) (support `type="line"` only) | { strokeWidth: 2, showInfo: false } | 4.3.0 |
| showUploadList | Whether to show default upload list, could be an object to specify `showPreviewIcon`, `showRemoveIcon`, `showDownloadIcon`, `removeIcon` and `downloadIcon` individually | boolean \| { showPreviewIcon?: boolean, showDownloadIcon?: boolean, showRemoveIcon?: boolean, previewIcon?: ReactNode \| (file: UploadFile) => ReactNode, removeIcon?: ReactNode \| (file: UploadFile) => ReactNode, downloadIcon?: ReactNode \| (file: UploadFile) => ReactNode } | true | function: 4.7.0 |
| withCredentials | The ajax upload with cookie sent | boolean | false | |
| onChange | A callback function, can be executed when uploading state is changing, see [onChange](#onchange) | function | - | |
| onChange | A callback function, can be executed when uploading state is changing. It will trigger by every uploading phase. see [onChange](#onchange) | function | - | |
| onDrop | A callback function executed when files are dragged and dropped into the upload area | (event: React.DragEvent) => void | - | 4.16.0 |
| onDownload | Click the method to download the file, pass the method to perform the method logic, and do not pass the default jump to the new TAB | function(file): void | (Jump to new TAB) | |
| onPreview | A callback function, will be executed when the file link or preview icon is clicked | function(file) | - | |
Expand All @@ -94,7 +94,7 @@ Extends File with additional props.

### onChange

> The function will be called when uploading is in progress, completed, or failed.
> 💡 The function will be called when uploading is in progress, completed, or failed.
When uploading state change, it returns:

Expand Down
Loading

0 comments on commit 8d7dd80

Please sign in to comment.