Populate Antd Input value depending on selected option - reactjs

I would like to populate an input value depending on the selected name before.
For exemple, if I select "FRANCILIENNE CONSEIL" I would like the right IBAN associated to be the value of the input.
I tried several things without success.
Here is a stackblitz of my code : https://stackblitz.com/edit/react-rc3me7

you can create some states to handle both select option & input for starter. Then update them through your handleChangeBeneficiary function.
in Option, would be ideal if you use a unique variable like beneficiaryId instead of name unless your name here also unique.
you can see the working code here: https://stackblitz.com/edit/react-rc3me7-gr3fmu
import React, { useState } from 'react'
const Demo = () => {
const [beneficiary, setbeneficiary] = useState()
const [iban, setiban] = useState()
const handleChangeBeneficiary = (value) => {
console.log(`selected ${value}`);
setbeneficiary(value)
// get selected iban
const selected = beneficiaries?.find(item => item?.beneficiaryId == value)
setiban(selected?.iban)
};
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const beneficiaries = [
{
iban: 'FR76167LQSDKJLKSQJ86538089',
name: 'FRANCILIENNE CONSEIL',
bic: 'TRZOFR21XXX',
beneficiaryId: '60c38ddf-63f9-4589-888b-27b7e1a50e53',
},
{
iban: 'FR291001DSKLFJSLKJ8633Z17',
name: 'MR NAMLA EMAD',
bic: 'PSSTFRPPCNE',
beneficiaryId: '60a11891-81ba-4ab2-9b92-ce4f461c2d50',
},
];
return (
<Form
{...layout}
name="test"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item label="Nom du bénéficiare" name="benef">
<Select
// defaultValue=""
value={beneficiary}
style={{ width: 300, marginBottom: 20 }}
onChange={handleChangeBeneficiary}
>
{beneficiaries.map((nom) => (
<Option value={nom.beneficiaryId}> {nom.name} </Option>
))}
</Select>
</Form.Item>
<Form.Item label="IBAN" name="iban">
<Input
// autoComplete="off"
style={{ marginBottom: 20 }}
placeholder={iban}
disabled/>
</Form.Item>
<Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};

You can update the value of IBAN as well. Please try the below code.
import React, {useState} from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, InputNumber, Button, Select } from 'antd';
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
/* eslint-disable no-template-curly-in-string */
const { Option } = Select;
/* eslint-enable no-template-curly-in-string */
const Demo = () => {
const [iban,setValue] =useState('')
const handleChangeBeneficiary = (value) => {
console.log(`selected ${value}`);
const ben= beneficiaries.filter((b)=>b.name===value)
setValue(value)
};
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const beneficiaries = [
{
iban: 'FR76167LQSDKJLKSQJ86538089',
name: 'FRANCILIENNE CONSEIL',
bic: 'TRZOFR21XXX',
beneficiaryId: '60c38ddf-63f9-4589-888b-27b7e1a50e53',
},
{
iban: 'FR291001DSKLFJSLKJ8633Z17',
name: 'MR NAMLA EMAD',
bic: 'PSSTFRPPCNE',
beneficiaryId: '60a11891-81ba-4ab2-9b92-ce4f461c2d50',
},
];
return (
<Form
{...layout}
name="test"
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item label="Nom du bénéficiare" name="benef">
<Select
defaultValue=""
style={{ width: 300, marginBottom: 20 }}
onChange={handleChangeBeneficiary}
>
{beneficiaries.map((nom) => (
<Option value={nom.name}> {nom.name} </Option>
))}
</Select>
</Form.Item>
<Form.Item label="IBAN">
<Input autoComplete="off" style={{ marginBottom: 20 }} value={iban}/>
</Form.Item>
<Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, document.getElementById('container'));

Related

Dynamic dropdown values are not displaying correctly

I have two antd select fields in a row and a + icon to add another row with two dropdowns as shown in the image.
On click of the first dropdown value, related data should be displayed in dropdown2, and click on + icon it will add two more dropdowns in the second row and respectively and the requirement is the same, onlick of 2nd row first dropdown value. related values will be displayed in the 2nd row 2nd drop-down field.
Issue:
2nd drop-down values are always the same for both rows. When I select the 2nd-row first dropdown value, related values show in 2nd row 2nd dropdown but the same values reflect in the first row second dropdown.
Below my code snippet and I am using antd Form to achieve this. For single row drop-downs it works as expected, but when I add another row by clicking on + icon, an issue occurs. Is there any other approach to implement this?
The code snippet I have added may not work in some environments.
import React, { useRef, useEffect, useState } from "react";
import { Form, Select, Col, Row, Button, Checkbox } from "antd/lib";
import { PlusOutlined, MinusOutlined } from "#ant-design/icons";
const { Option } = Select;
const DropdownComponent = (props) => {
const addBtnRef = useRef(null);
const [dropDownOneData, setDropDownOneData] = useState([]);
const [dropDownTwoData, setDropDownTwoData] = useState([]);
const [dropDownOneValue, setDropDownOneValue] = useState("");
const dropDownOneTwoValues: [
[
{
dropDownOne: {
key: "test_t";
value: "test";
};
dropDownTwo: [
{
key: "key1";
value: "Value1";
},
{
key: "key2";
value: "Value2";
}
];
}
],
[
{
dropDownOne: {
key: "test_t1";
value: "test1";
};
dropDownTwo: [
{
key: "key3";
value: "Value3";
},
{
key: "key4";
value: "Value4";
}
];
}
]
];
useEffect(() => {
addBtnRef.current.click();
// set dropdownone values
const dropDownOneData = dropDownOneTwoValues?.map(
(searchField) => searchField[0].dropDownOne
);
setDropDownOneData(dropDownOneData);
}, []);
useEffect(() => {
// set related dropDownTwo values on selected dropdownOne value
const dropDownTwoValues = dropDownOneTwoValues
.flat()
.filter((values) => values.dropDownOne.key === dropDownOneValue)
.flatMap((value) => value.dropDownTwo);
setDropDownTwoData(dropDownTwoValues);
}, [dropDownOneValue]);
const handleDropDownOne = (value) => {
setDropDownOneValue(value);
};
function renderDropDownValues(options) {
return options.map((option) => {
if (option.key && option.value) {
return (
<Option
key={option.key}
value={option.key}
disabled={option.disabled}
>
{option.value}
</Option>
);
}
return (
<Option key={option} value={option}>
{option}
</Option>
);
});
}
return (
<>
<Row>
<Col>
<Form.List>
{(fields, { add, remove }) => {
{
console.log("fields...", fields);
}
return (
<div
className="border"
style={{
padding: "20px",
marginBottom: "25px",
marginTop: "-30px"
}}
>
{fields.map((value, index) => {
return (
<Row key={index} style={{ marginBottom: 8 }}>
<Col>
<Form.Item
rules={[
{ required: true, message: "Select a value" }
]}
name={value.Name}
>
<Select
key={index}
className="w-100"
showSearch={true}
optionFilterProp="children"
filterOption={(input, option) =>
option?.children
.toLowerCase()
.includes(input.toLowerCase())
}
placeholder="Select"
onChange={(value) => handleDropDownOne(value)}
value={dropDownOneValue}
>
{renderDropDownValues(dropDownOneData)}
</Select>
</Form.Item>
</Col>
<Col>
<Form.Item
rules={[
{ required: true, message: "Select a value" }
]}
name={value.name}
>
<Select
className="w-100"
showSearch={true}
optionFilterProp="children"
filterOption={(input, option) =>
option?.children
.toLowerCase()
.includes(input.toLowerCase())
}
placeholder="Select"
>
{renderDropDownValues(dropDownTwoData)}
</Select>
</Form.Item>
</Col>
</Row>
);
})}
<Row justify="end">
<Col>
<Form.Item>
<Button
ref={addBtnRef}
shape="circle"
size="small"
className="center"
data-testid="add-clause-btn"
icon={
<PlusOutlined
className="primary-color"
style={{ marginTop: "1px" }}
/>
}
onClick={() => {
add();
}}
/>
</Form.Item>
</Col>
</Row>
</div>
);
}}
</Form.List>
)
</Col>
</Row>
</>
);
};
export default DropdownComponent;
You need to have unique Form.Item name for every row.
Try this,
name={[index, value.Name]}
and provide a name for Form.List also, name={"something"}

How to Reset a form when I click submit button in React

I am working on a React project, For designing I am using Ant design framework. I have a form in that form when I entered all details in Input form and when I click submit button the Form has to be Reset, I tried to Reset a form after clicking submit button. but it is showing this kind of error. TypeError: Cannot read property 'reset' of null
So please help me to resolve this error
This is my code App.js
import React, { useRef, useState } from "react";
import { Row, Col, Button, Card, Form, Input, Select } from "antd";
import axios from 'axios'
import 'antd/dist/antd.css';
import {
SearchOutlined,
StopOutlined,
UserOutlined,
LeftOutlined,
DoubleRightOutlined,
} from "#ant-design/icons";
import './App.css';
const App = () => {
const { Option } = Select;
const [data, setData] = useState({});
const testData = async () => {
try {
const res = await axios.post('http://localhost:8000/api/user', data);
console.log(res);
} catch (error) {
console.log(error);
}
}
const handleChange = ({ target }) => {
const { name, value } = target;
const newData = Object.assign({}, data, { [name]: value });
setData(newData);
}
const handleSubmit = (e) => {
e.preventDefault();
console.log(data);
testData()
};
const myForm = useRef(null)
const resetForm = () => {
myForm.current.reset();
}
const prefixSelector = (
<Form.Item name="prefix" noStyle>
<Select
style={{
width: 50,
// height: 10,
}}
>
<Option value="86">+86</Option>
<Option value="87">+87</Option>
</Select>
</Form.Item>
);
return (
<div>
<div className="customizedCards">
<Card className="cardStyle">
<div className="main-form">
<h5 className="idDetails">StudentDETAILS</h5>
<Form style={{marginLeft: "-10px"}} ref={myForm}>
<Form.Item
name="name"
noStyle
rules={[{ required: true, message: 'firstname is required' }]}
>
<Input type="text" name='first_name' style={{ width: 400 }} onChange={handleChange} placeholder="Firstname" />
</Form.Item>
<Form.Item
name="name"
noStyle
rules={[{ required: true, message: 'lastname is required' }]}
>
<Input type="text" name='last_name' style={{ width: 400 }} onChange={handleChange} placeholder="Lastname" />
</Form.Item>
<Form.Item
name="name"
noStyle
rules={[{ required: true, message: 'email is required' }]}
>
<Input type="email" name='email' style={{ width: 400 }} onChange={handleChange} placeholder="Email" />
</Form.Item>
<Form.Item
name="phone"
rules={[
{
required: true,
message: 'Please input your phone number!',
},
]}
>
<Input type="number" name='phone_number' addonBefore={prefixSelector} style={{ width: 400 }} onChange={handleChange} placeholder="Phone Number" />
</Form.Item>
<Button onClick={(e) => handleSubmit(e), resetForm()} className="submit" type="primary" >Submit</Button>
</Form>
</div>
</Card>
</div>
</div>
)
}
export default App
```
As said here you just have a syntax trouble.
Try this instead:
const myForm = useRef(null)
const resetForm = () => {
myForm.reset();
}

Antd Select not setting initial value

I have an issue in setting the initial value in antd Select
const options=[{name:'john',id:1},{name:'jack',id:2},{name:'jill',id:3}]
<Form initialValues={{user:3}}>
<Form.Item name="user" label="Select user">
<Select value="3">
{options.map((user,index)=><Option key={index} value={user.id}>{user.name}</Option>)}
</Select>
</Form.Item>
</Form>
It's not selecting the initial value. Any idea in this. is this a correct way of implementing it, please help
The below is a simple demo of Select Component in Antd Form
I am wondering whether the options come from the store or other components? So the form does not get the initial values once the form is mounted. If it comes from other source, you need to subscribe the initial values if it changes to reset the antd form like
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button, Checkbox, Select } from 'antd';
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
const tailLayout = {
wrapperCol: {
offset: 8,
span: 16,
},
};
// useEffect(() => {
// form.resetFields()
// form.setFieldsValue({
// productName: productName
// })
// }, [initialValues]);
const userNameOptions = [{name:'john',id:1},{name:'jack',id:2},{name:'jill',id:3}]
const Demo = () => {
const onFinish = (values) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
return (
<Form
{...layout}
name="basic"
initialValues={{
remember: true,
username: 3
}}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item
label="Username"
name="username"
rules={[
{
required: true,
message: 'Please input your username!',
},
]}
>
<Select value='3'>
{userNameOptions.map((item, index) => (
<Select.Option key={index} value={item.id}>
{item.name}
</Select.Option>
))}
</Select>
</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>
);
};
ReactDOM.render(<Demo />, document.getElementById('container'));
I have this working in ant design 4.
If you only need to set the value once use defaultValue and pass a string prop
defaultValue={!!props.DefaultString && claimId}
You can however set the values for both the current value and the options by using form.setFieldsValue in useEffect.
e.g.
useEffect(() => {
form.setFieldsValue({
SelectValue: !!props.selectItemValue && props.props.claimId,
SelectableOptions: (!!props.selectableOptions? props.selectableOptions : undefined)
);
}
}, [props,form]);
<Form.Item name="SelectValue" >
<Select >
{!!props.selectableOptions && props.selectableOptions.map((opt) => <Option key={opt.id} value={opt.id}>{opt.name}</Option>)}
</Select>
</Form.Item>
NB: Use the props directly rather than the fieldValue for the options

React ant design reset only one input filed

Im using my project for React ant design 4 . I have some conflict on the form . I want to know how to reset only one (Note) field any one know the solution
Thanks
stazkblitz here
code here
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button, Select } from 'antd';
const { Option } = Select;
const layout = {
labelCol: {
span: 8,
},
wrapperCol: {
span: 16,
},
};
const tailLayout = {
wrapperCol: {
offset: 8,
span: 16,
},
};
const Demo = () => {
const [form] = Form.useForm();
const onGenderChange = (value) => {
switch (value) {
case 'male':
form.setFieldsValue({
note: 'Hi, man!',
});
return;
case 'female':
form.setFieldsValue({
note: 'Hi, lady!',
});
return;
case 'other':
form.setFieldsValue({
note: 'Hi there!',
});
return;
}
};
const onFinish = (values) => {
console.log(values);
};
const onReset = () => {
form.resetFields();
};
const onFill = () => {
form.setFieldsValue({
note: 'Hello world!',
gender: 'male',
});
};
return (
<Form {...layout} form={form} name="control-hooks" onFinish={onFinish}>
<Form.Item
name="note"
label="Note"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
<Form.Item
name="gender"
label="Gender"
rules={[
{
required: true,
},
]}
>
<Select
placeholder="Select a option and change input text above"
onChange={onGenderChange}
allowClear
>
<Option value="male">male</Option>
<Option value="female">female</Option>
<Option value="other">other</Option>
</Select>
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues.gender !== currentValues.gender}
>
{({ getFieldValue }) => {
return getFieldValue('gender') === 'other' ? (
<Form.Item
name="customizeGender"
label="Customize Gender"
rules={[
{
required: true,
},
]}
>
<Input />
</Form.Item>
) : null;
}}
</Form.Item>
<Form.Item {...tailLayout}>
<Button type="primary" htmlType="submit">
Submit
</Button>
<Button htmlType="button" onClick={onReset}>
Reset
</Button>
<Button type="link" htmlType="button" onClick={onFill}>
Fill form
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, document.getElementById('container'));
You can add an array of namePath in your form.resetFields call
const onReset = () => {
form.resetFields(["note"]);
};
Just tested it with your code and it works : https://stackblitz.com/edit/react-nazmet-jh2cc1?file=index.js
More info : https://ant.design/components/form/#FormInstance

Disable form.item 1 if form.item 2 is filled in

I want to hide form.item 1 if form.item 2 is filled in and the other way around.
I want to do it for the following code but i cant find the solution to this.
<Form.Item label="Url">
{getFieldDecorator('url')(<Input/>)}
</Form.Item>
<Form.Item label="Standaard Urls" >
{getFieldDecorator('url_id', {})(this.getSelectUrls())}
</Form.Item>
Basically i want too know how i can hide 1 form.item and the rest i can do myself
You need to use onFieldsChange of Form.create, that keeps your Form uncontrollable which is the cleanest way.
Wrap your Form with a state, pass it and use onFieldsChange like so:
const FormContainer = () => {
const [isVisible, setIsVisible] = useState(true);
const onFieldsChange = (_, changedFiels) => {
const { password } = changedFiels;
if (password) {
console.log(`Now changing ${password.name}`);
setIsVisible(false);
}
};
const ValidatedFields = Form.create({ onFieldsChange })(MyForm);
return <ValidatedFields isVisible={isVisible} />;
};
Warning: You need to figure how you want to "remove" the form field, it depends on if you need its state or not, for this you can use display CSS property:
// Will unmount the item and lose it state
{ isVisible && <Form.Item>...}
// Will keep the state and hide the item
<Form.Item style={{ display: isVisible ? 'auto' : 'none' }}>...
Full code:
In this example, you can write in the password field and it will hide other forms items:
import React, { useState } from 'react';
import ReactDOM from 'react-dom';
import { Input, Form, Icon } from 'antd';
import 'antd/dist/antd.css';
import './index.css';
const FormContainer = () => {
const [isVisible, setIsVisible] = useState(true);
const onFieldsChange = (_, changedFiels) => {
const { password } = changedFiels;
if (password) {
console.log(`Now changing ${password.name}`);
setIsVisible(false);
}
};
const ValidatedFields = Form.create({ onFieldsChange })(MyForm);
return <ValidatedFields isVisible={isVisible} />;
};
const MyForm = ({ form, isVisible }) => {
const { getFieldDecorator, validateFields } = form;
const handleSubmit = e => {
e.preventDefault();
validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
};
return (
<Form onSubmit={handleSubmit} className="login-form">
{isVisible && (
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true, message: 'Please input your username!' }]
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Item 1"
/>
)}
</Form.Item>
)}
<Form.Item style={{ display: isVisible ? 'auto' : 'none' }}>
{getFieldDecorator('username2', {
rules: [{ required: true, message: 'Please input your username!' }]
})(
<Input
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="Item 2"
/>
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }]
})(
<Input
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="Type here to hide other forms"
/>
)}
</Form.Item>
</Form>
);
};
ReactDOM.render(<FormContainer />, document.getElementById('root'));
const [showItem1, setShowItem1] = useState(true);
const [showItem2, setShowItem2] = useState(true);
onKeyPress = {() => {setShowItem1(true); setShowItem1(false); }}
onKeyPress = {() => {setShowItem1(false); setShowItem1(true); }}
{
showItem1 &&
<Form.Item label="Url">
{getFieldDecorator('url')(<Input/>)}
</Form.Item>
}
{
showItem2 &&
<Form.Item label="Standaard Urls" >
{getFieldDecorator('url_id', {})(this.getSelectUrls())}
</Form.Item>
}

Resources