antd forms - complex child elements of <Form.Item> - reactjs

I have a antd form like this:
return(
<Form
{...layout}
form={form}
onFinish={onFinish}
>
<Form.Item
label="Bezeichnung"
name="name"
initialValue={resource ? resource.name : ""}
rules={[{ required: true, message: 'Bitte Bezeichnung eingeben.' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Farbe"
name="color"
initialValue={resource ? resource.color : undefined}
>
<Input />
</Form.Item>
<ColorPickerButton
onColorChange={(color) => {
form.setFieldsValue({
color: color.hex
});
}}
/>
</Form>
);
As you can see here, i hav an extra button (independenly of the form) which acts as a color-picker. The chosen color is then used with
form.setFieldsValue({
color: color.hex
});
My question is now: Is there a more convenient way of putting together the <Input /> component with the <ColorPickerButton />component to use it that way:
<Form.Item
label="Farbe"
name="color"
initialValue={resource ? resource.color : undefined}
>
<ColorPickerInput />
</Form.Item>

Do you want some kinds of "auto binding" between Form.Item and ColorPickerInput? You can try to pass form and name to ColorPickerInput component, and call form.setFieldsValue({[name]: value}) within ColorPickerButton.onColorChange to update it.

Related

How to get error message by getFieldError in AntD Form?

I'm validating form with Ant Design but I have a problem with getFieldError(). I need to get the error messages by the field name of Form.Item but it not works.
Here's my code not works below:
...
<Form form={form} name="login_form" onFinish={onFinish} scrollToFirstError>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Password cannot be empty!',
},
]}
help='' // hide validating message.
>
<>
{({ getFieldError }) => console.log(getFieldError('password'))}
//it not logging anything when submit form trigger error
<Input.Password placeholder="Enter your password" />
</>
</Form.Item>
</Form>
How can I solved this problem?
Your console.log will invoke, every time your component renders, so you need to rerender your component whenever validation applies on the form. To handle this situation you can use render prop with Form component, like this:
function CustomFormItem({ error, ...other }) {
console.log(error)
return <Input.Password placeholder="Enter your password" {...other} />;
}
function MyForm() {
const [form] = Form.useForm();
const onFinish = (values) => {
console.log(values);
};
return (
<Form
form={form}
name="login_form"
onFinish={onFinish}
scrollToFirstError
>
{(values,formInstance) => {
return (
<>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Password cannot be empty!',
},
]}
help="" // hide validating message.
>
<CustomFormItem error={formInstance.getFieldError('password')} />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</>
);
}}
</Form>
);
}
Consider that with above implementation, render prop will call with every change on the form.
Use can use getFieldError(); like the code example below
Function as Child Component is not working perfectly inside <Form.Item> component as of now.
<Form {...layout} form={form} name="control-hooks" onFinish={onFinish}>
{(values, formInstance) => {
console.log(formInstance.getFieldError("password")[0]);
return (
<>
<Form.Item
name="password"
label="Password"
rules={[
{
required: true
}
]}
>
<Input />
</Form.Item>
</>
);
}}
</Form>

using ant design switch inside Forms

What's the correct way to use ant design switch inside, I could not get much from the official documentation.
Switch-Ant Design
Here's how I am using it.
<Form form={form} layout="vertical">
<Form.Item
label="Description"
name="description"
rules={[{ required: true, message: 'Enter a description' }]}
>
<Input placeholder="Enter Description" />
</Form.Item>
<Form.Item name="switch" noStyle valuePropName="checked">
<Switch checkedChildren="Yes" unCheckedChildren="No" />
<span>Chargable</span>
</Form.Item>
<Button
onClick={() => {
form
.validateFields()
.then((values) => {
form.resetFields()
onCreate(values)
})
.catch((info) => {
console.log('Validate Failed:', info)
})
}}
>
Save
</Button>
</Form>
onCreate does no take the value from the switch, It does take it from the description
const onCreate = (values) => {}
I was able to fix it but doing the following.
<td>
<Form.Item valuePropName="checked" name="status" noStyle>
<Switch checkedChildren="Yes" unCheckedChildren="No" />
</Form.Item>
<span className="ml-2">Status Enabled</span>
</td>
I guess your values are {description: "foo", switch: undefined}?
In my demo, switch demo, I add initialValue to Switch, so when I get values from the form, I get {description: "111", switch: true}.
I don't know whether this is what your mean.
or you can use like this
<Form.Item label="foo">
<Form.Item name="bar">
<Switch />
</Form.Item>
<span className="ant-form-text">Some text you want</span>
</Form.Item>
This is because you must only have one child inside a Form.Item component. Remove the span besides your Switch component and it will work.

ant design form async-validator warning

I am using antd forms and rules and when im submiting a form i get warnings like:
async-validator: ["Please enter username"].
I tried { suppressWarning: true } but it didn't work, the warning is not the same text in the rule its the default template text
antd: ^4.6.4
<Form
{...layout}
name="basic"
initialValues={{
remember: true,
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
label="Username"
name="username"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[
{
required: true,
message: 'Please input your password!',
},
]}
>
<Input.Password />
</Form.Item>
<Form.Item {...tailLayout} name="remember" valuePropName="checked">
<Checkbox>Remember me</Checkbox>
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
As described on the async-validator page (https://github.com/yiminghe/async-validator)
At the entry point to your app you can do the following to disable the warning messages.
import Schema from 'async-validator';
Schema.warning = function(){};
For antd >4.20.0, use the following line in the App.jsx, after last import instruction...
global.ASYNC_VALIDATOR_NO_WARNING = 1;

Reactjs antd defaultValue return undefined

im trying to make an edit function, the problem come when im trying to get the value from the form, say a user is editing his name, but he does not edit his address, this will make address is undefined even though i already set a defaultValue inside it, this works before in my non antd form, here is my code
form :
<Form onFinish={this.edit}>
<Typography>Email</Typography>
<Form.Item
name="email"
>
<Input defaultValue={user.Email} value={user.Email} className="email form-control col-sm-6"/>
</Form.Item>
<Typography>Full Name</Typography>
<Form.Item
name="name"
>
<Input defaultValue={user.FullName} value={user.FullName} className="email form-control col-sm-6"/>
</Form.Item>
<Typography>Admin</Typography>
<Form.Item
name="admin"
>
{
(user.IsAdministrator)
? <div>
<Select value="yes">Admin
<Select.Option value="no">Not Admin</Select.Option>
</Select>
</div>
: <div>
<Select value="no">Not admin
<Select.Option value="yes">Admin</Select.Option>
</Select>
</div>
}
</Form.Item>
<Typography>Active Status</Typography>
<Form.Item
name="aktif"
>
{
(user.IsActive)
? <Toggle className="switch-lg" checked/>
: <Toggle className="switch-lg"/>
}
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" className="login col-md-10">Submit</Button>
and here is how i get the value :
edit(values){
const name = values.name
const aktif = values.aktif
const index = this.state.id
console.log(values)
}
thanks before, anyhelp will be appreciated
As mentioned in the docs,
You cannot set value for each form control via value or defaultValue prop, you should set default value with initialValues of Form.
Example below:
<Form
onFinish={onFinish}
initialValues={{
residence: ['zhejiang', 'hangzhou', 'xihu'],
prefix: '86',
}}
>

Other validation message is triggering instead of my message when using Ant design getFieldDecorator

I am using Ant design and this is my form when I click on save I am getting this type of validation msg instead of red bordered Antd validation msg
I want validation error like this which is shown in AntD documents.
https://codesandbox.io/s/do52z
I have writter my function like this
<Form id="myForm" onSubmit={this.handleSubmit}>
<Form.Item label="Code">
<CustomInput
form={this.props.form}
type="text"
disabled={this.state.disableFields}
name="code"
id="code"
placeholder=""
required={true}
errorMsg={"Please input code!"}
/>
</Form.Item>
</Form>
This is my custom Input
const CustomInput = ({
form, id, name, placeholder, required, errorMsg, type, disabled,}: Props) => {
return form.getFieldDecorator(id, {
rules: [
{
required: required,
message: errorMsg
}
]
})(
<Input
type={type}
name={name}
id={id}
disabled={disabled}
placeholder={placeholder}
className={name === "code" ? "code-input" : "input-box"}
/>
);
};
export default CustomInput;
and this is my save button
<Button
className="save-btn"
htmlType="submit"
form="myForm"
>
Save
</Button>
I think I am missing something little here. Thanks in advance
Ant design input doesn't have required prop..
Required prop should be give inside form.item rules prop.
Since you have given reqired to input tag it will cause Chrome to display a prompt that the user to fill out the field.
Update based on comment
Move formitem tag inside custominput component and try again.
<Form id="myForm" onSubmit={this.handleSubmit}>
<CustomInput
form={this.props.form}
type="text"
disabled={this.state.disableFields}
name="code"
id="code"
placeholder=""
required={true}
errorMsg={"Please input code!"}
/>
</Form>
..
const CustomInput = ({
form, id, name, placeholder, required, errorMsg, type, disabled,}: Props) => {
return(
<Form.Item label="Code">
{form.getFieldDecorator(id, {
rules: [
{
required: required,
message: errorMsg
}
]
})(
<Input
type={type}
name={name}
id={id}
disabled={disabled}
placeholder={placeholder}
className={name === "code" ? "code-input" : "input-box"}
/>
)}
</Form.Item>
)
};

Resources