Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getFieldDecorator装饰多个antd组件 #3866

Closed
xiongran opened this issue Nov 16, 2016 · 15 comments
Closed

getFieldDecorator装饰多个antd组件 #3866

xiongran opened this issue Nov 16, 2016 · 15 comments
Labels
help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. Usage

Comments

@xiongran
Copy link

发生问题的环境是:

  • antd 版本: 2.4.2
  • 操作系统及其版本: WIN7专业版
  • 浏览器及其版本: chrome 50.0.2661.87 m

您期待的结果是:

我希望getFieldDecorator装饰多个antd组件以实现复杂些的功能。比如要实现生效时间,包括生效时间值和时间单位,需要使用InputNumber和Select 两个antd组件。

您做了什么?请提供尽可能详细的重现步骤。

1、封装InputUnit组件
使用getFieldDecorator装饰的组件会自动给组件添加onChange和value属性,value对应getFieldDecorator的initialValue。在InputUnit中把InputNumber和Select 的onChange都对应到props的onChange,这里改变了onChange的输入参数,使用{name: fieldName, value: v}作为输入参数,这样在getValueFromEvent中处理的时候就可以区分处理的是哪个fieldName的值。
image
2、getFieldDecorator装饰InputUnit组件
getFieldDecorator装饰InputUnit组件就跟装饰单个antd组件的用法基本一样了,只是在getValueFromEvent处理的时候做点小改动就可以了,在getDecoratorValue中可以得到每个fieldName和它对应的值,使用setFieldsValue保存就可以了。
image
getDecoratorValue方法实现:
image

实际上的结果是:

最终效果就跟下面图一样了,时间单位有:分、时、天、月。
image

如果我不把InputNumber和Select封装成InputUnit组件让它们成一个整体,而是使用getFieldDecorator分别封装InputNumber和Select,那么校验的提示文字显示和去除会有问题。比如当我输完最快生效时间的时候是提示有错误的,但如果我选择更小的最快生效时间单位,那其实最快生效时间是比最晚生效时间早的,校验成功了。但是之前的错误提示信息是由于最快生效时间那个组件引起的,虽然通过调整最快生效时间单位这个组件使校验通过了,但是并不能消除不是由它引起的错误。我不知道除了我上述方法可以满足我的需求以外,antd是否还有其他的方式可以更方便的使用?比如1个校验逻辑是由4个组件(A、B、C、D)值共同控制,当A值错误导致校验失败而提示错误信息,但选择B组件使得校验通过,可不可以消除由A组件引起的错误?

@benjycui
Copy link
Contributor

Form.Item 自动生成提示只是个优化,特殊需求的话,自行控制提示文字的显示和隐藏,参考:https://ant.design/components/form/#components-form-demo-without-form-create

@benjycui
Copy link
Contributor

把多个表单域封装成一个也是不错的思路 👍

参考:https://ant.design/components/form/#components-form-demo-customized-form-controls

@benjycui
Copy link
Contributor

benjycui commented Nov 17, 2016

感觉可以作为 demo,处理一个 Form.Item 内有多个表单域但只需要一个提示的情况。

@xiongran 把这个 demo 更新下,来个 PR?

@benjycui
Copy link
Contributor

场景直接用你现在的真实场景即可。

@benjycui benjycui added help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. Usage labels Nov 17, 2016
@afc163
Copy link
Member

afc163 commented Nov 17, 2016

截图里发现一个 InputNumber 的对齐问题:http://codepen.io/anon/pen/BQQBmK?editors=0010

@guoxiangwen
Copy link

getFieldDecorator中有多个Input并列的时候,如果添加了rules 那么所有的Input都会生效,怎么让其中某一个Input对rules生效?

@zhaodongxx
Copy link

zhaodongxx commented Aug 2, 2018

@xiongran 的这种方式有两个问题

  1. 可能导致自定义组件的value为空。是因为 属性 getValueFromEvent 导致的,去掉即可
  2. 而且多余,直接把在getDecoratorValue方法中拼接的value在自定义组件内部onChange返回就可以了
return (
            <InputGroup compact>
                <InputNumber
                    style={{ width: 100 }}
                    placeholder={data[0].placeholder}
                    value={lowValue}
                    onChange={v => onChange({
                        [data[0].filedName]: v,
                        [data[1].filedName]: hightValue
                    })}
                />
                <Input
                    style={{
                        width: 30,
                        borderLeft: 0,
                        pointerEvents: 'none',
                        backgroundColor: '#fff'
                    }}
                    placeholder="-"
                    disabled
                />
                <InputNumber
                    style={{ width: 100 }}
                    placeholder={data[1].placeholder}
                    value={hightValue}
                    onChange={v => onChange({
                        [data[0].filedName]: lowValue,
                        [data[1].filedName]: v
                    })}
                />
            </InputGroup>
        )

@alukaa
Copy link

alukaa commented Jan 28, 2019

学习了,思路很不错。我觉得可以把from value 绑定放在自定义的组件中重用度更高,我是这样搞的.
2019-01-29 00-18-04
2019-01-29 00-19-21

  1. 传递prop form
  2. 自定义组件调用prop form setFieldsValue

@alukaa
Copy link

alukaa commented Jan 28, 2019

改进了一下,把fieldName也传递进去更好
2019-01-29 00-24-53
2019-01-29 00-26-58

@Kaiser-daisy
Copy link

自定义组件InputUnit中的两个select组件怎么做独立正则校验呢?我实现一个组件同样有多个Input输入,被一个getFieldDecorator包装, 使用validator方法定义校验,一个Input校验不通过,整个组件都被被标记

@lcoder
Copy link

lcoder commented Sep 6, 2019

是否可以设计一个hiddenLabelAPI
这样子可以在可以模拟在一个Form.Item,里面有多个getFieldDecorator的数据

<Label title="姓名和年龄">
    <Row>
        <Col>
            <Form.Item
                hiddenLabel
            >
            {
                getFieldDecorator('name', {
                    rules: [
                        {
                        required: true,
                        },
                    ],
                })(
                    <Input />
                )
            }
            </Form.Item>
        </Col>
        <Col>
        <Form.Item
            hiddenLabel
        >
        {
            getFieldDecorator('age', {
                rules: [
                    {
                    required: true,
                    },
                ],
            })(
                <Input />
            )
        }
        </Form.Item>
        </Col>
    </Row>
</Label>

@chenyu1990
Copy link

@zhaodongxx @benjycui @xiongran 如果field是'humen[age]',这种怎么办?

@lcoder
Copy link

lcoder commented Nov 12, 2019

getFieldDecorator 的参数 id | 必填 输入控件唯一标志。支持嵌套式的写法。humen.age

@chenyu1990
Copy link

chenyu1990 commented Nov 12, 2019

@zhaodongxx 用你的方式,值从string变成了object

我直接传v, onChange(v),好了

@tangtangtangtangtang
Copy link

自定义组件InputUnit中的两个select组件怎么做独立正则校验呢?我实现一个组件同样有多个Input输入,被一个getFieldDecorator包装, 使用validator方法定义校验,一个Input校验不通过,整个组件都被被标记

想知道这个办法能解决吗?好像form里面的input是根据context来获取的状态?如果是这样的话我并不持有那个context是不是没办法解决啊。。。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted The suggestion or request has been accepted, we need you to help us by sending a pull request. Usage
Projects
None yet
Development

No branches or pull requests

10 participants