deselect radio button from array list in react js - reactjs

I have an array list, where every record will have radio button, when user clicks on one radio it should select it and when user clicks on another radio button the first selected record button should deselect radio button.
Please find sanbox link below:
sandbox link
code:
const handlesubmit = (formdata) => {
console.log(formdata);
};
const renderCard = (card, index) => {
return (
<Col span={7} className="card-background">
<h3 style={{ textAlign: "center" }}>{card.planType}</h3>
<hr />
<Form.Item name="selectedPlan">
<Row>
<Col span={16} offset={2}>
{card.planDetails[0].name}
</Col>{" "}
<Col span={5} offset={1}>
{card.planDetails[0].numOfSession}
</Col>
<Col span={16} offset={2}>
{card.planDetails[1].name}
</Col>{" "}
<Col span={5} offset={1}>
{card.planDetails[1].numOfSession}
</Col>
<Col span={16} offset={2}>
{card.planDetails[2].name}
</Col>{" "}
<Col span={5} offset={1}>
{card.planDetails[2].numOfSession}
</Col>
</Row>
</Form.Item>
<hr />
<div style={{ textAlign: "center" }}>
<Radio onChange={() => setSelectedPlan(card)}>
Pay {card.planAmount}
</Radio>
</div>
</Col>
);
};

you need checked your radio buttons based on plan state
for example
<Radio
checked={selectedPlan === card.planAmount}
onChange={() => setSelectedPlan(card.planAmount)}>
Pay {card.planAmount}
</Radio>

You can define your state like:
const [selectedPlan, setSelectedPlan] = useState(0);
And do something like:
const setSelected = (event, index) => {
setSelectedPlan(index);
};
Finally Change Radio to :
<Radio
checked={selectedPlan == index ? true : false}
name="radio"
onChange={(e) => setSelected(e, index)}
>
Pay {card.planAmount}
</Radio>

Related

Antd dynamic form - how can I change form elements based on current values?

I have a dynamic Antd form where I can enter menu elements. The user can add, remove and reorder menu elements. The dynamic fields work fine, but I have a radio button for each dynamic element indicating that the corresponding menu element is an external URL or an internal page. I need to display different input elements if the user chooses URL or internal page. I tried the method listed in the Antd documentation, but it is for static fields and it doesn't seem to be working for dynamic elements.
My code so far is:
<Form.List name={"menuTree"}>
{(fields, { add, remove }) => (
<>
{fields.map((field, index) => (
<Row id={"menu-row-" + index} key={index}>
<Col span={8}>
<Form.Item label="Title" name={[field.name, "title"]} key={"title" + index + Math.random()}>
<Input />
</Form.Item>
</Col>
<Col span={4}>
<Form.Item label="Type" name={[field.name, "type"]}>
<Radio.Group>
<Radio value={"link"}>URL</Radio>
<Radio value={"page"}>Page</Radio>
</Radio.Group>
</Form.Item>
</Col>
<Col span={9}>
<Form.Item
// label="URL"
// name={[field.name, "url"]}
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues.type !== currentValues.type}>
{({ getFieldValue }) => {
return getFieldValue("type") === "link" ? (
<Form.Item name={[field.name, "url"]} label="URL">
<Input />
</Form.Item>
) : (
<Form.Item name={[field.name, "page"]} label="Page">
<Input />
</Form.Item>
)
}}
<Input />
</Form.Item>
</Col>
<Col span={2}>
<Form.Item>
<Button htmlType="button" onClick={() => moveUp(index)}>
<CaretUpOutlined />
</Button>
<Button htmlType="button" onClick={() => moveDown(index)}>
<CaretDownOutlined />
</Button>
</Form.Item>
</Col>
<Col span={1}>
<Button htmlType="button" onClick={() => removeMenuItem(index)}>
<MinusOutlined />
</Button>
</Col>
</Row>
))}
<Button type="dashed" onClick={() => addMenuItem()} block icon={<PlusOutlined />}>
Add menu item
</Button>
</>
)}
</Form.List>
How can I achieve to change the input on a per line basis whenever the user changes the value of the radio button?
You are trying to get type value with wrong name path. getFieldValue expects the complete path when you want to get any value.
You form list name is menuTree. Since it's a list, your namepath will look like this:
getFieldValue(['menuTree', field.name, 'type'])
<Form>
<Form.List name={'menuTree'}>
{(fields, { add, remove }) => (
<>
{fields.map((field, index) => (
<Row id={'menu-row-' + index} key={index}>
<Col span={8}>
<Form.Item label='Title' name={[field.name, 'title']} key={'title' + index + Math.random()}>
<Input />
</Form.Item>
</Col>
<Col span={4}>
<Form.Item label='Type' name={[field.name, 'type']}>
<Radio.Group>
<Radio value={'link'}>URL</Radio>
<Radio value={'page'}>Page</Radio>
</Radio.Group>
</Form.Item>
</Col>
<Col span={9}>
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) =>
prevValues?.menuTree?.[field.name]?.type !== currentValues?.menuTree?.[field.name]?.type
}
>
{({ getFieldValue }) => {
return (
<>
{getFieldValue(['menuTree', field.name, 'type']) === 'link' ? (
<Form.Item name={[field.name, 'url']} label='URL'>
<Input />
</Form.Item>
) : (
<Form.Item name={[field.name, 'page']} label='Page'>
<Input />
</Form.Item>
)}
</>
);
}}
</Form.Item>
</Col>
<Col span={2}>
<Form.Item>
<Button htmlType='button' onClick={() => {}}>
<CaretUpOutlined />
</Button>
<Button htmlType='button' onClick={() => {}}>
<CaretDownOutlined />
</Button>
</Form.Item>
</Col>
<Col span={1}>
<Button htmlType='button' onClick={() => remove(field.name)}>
<MinusOutlined />
</Button>
</Col>
</Row>
))}
<Button type='dashed' onClick={() => add()} block icon={<PlusOutlined />}>
Add menu item
</Button>
</>
)}
</Form.List>
</Form>

useRef only gets last values from mapped form antd Reactjs

I get a bunch of references from an API, I want to insert each Reference with its quantity, I am using antd form useRef
and I get undefined values
const formRef =useRef();
const submitFunction= (values) => {
formRef.current.validateFields().then((values) => {
console.log("Values:", values);
});
};
{reference.map((e, index) => (
<Form ref={formRef}
initialValues={{
["Ref"]: e.reference
}}>
<div>
<Row style={{ backgroundColor: "darkcyan" }} gutter={8}>
<Col span={5}>
<Form.Item label="Ref" name="Ref" labelCol={{ span: 6 }}>
<Input key={index} defaultValue={e.reference} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="quantity">
<InputNumber key={index} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item>
<Button onClick={() => submitFunction()}>
click me
</Button>
</Form.Item>
</Col>
</Row>
</div>
</Form>
))}
referencesList
Maybe it is too late to answer the question. It seems that because you have a list of Form component and formRef is connected to each form, logically the reference value of the forms are replaced one by one in the formRef till it gets to the last one. If you want to prevent that you can initialize formRef as an empty array like this:
const formRef = useRef([]);
And define ref prop of the Form component like so:
ref={el => {
if (el) formRef.current[index] = el
}}
finally change submitFunction :
const submitFunction = (value) => {
formRef.current.map(form => {
form.validateFields().then((values) => {
console.log("Values:", values);
});
})
};

React AntD Form dynamic form automatically make list of fields, or remove add button after

I am working on a react app on rails using AntD. I am trying to make a form.list that has thirty items with four fields each.
I was was able to make a form with dynamically added fields by adapting this [codesandbox example][1] It worked great (in my example code below I made it rooms), I can add a room one at a time and the button provides four fields to enter information on the room and that passes into my controller and saves.
The problem is I want it to automatically map 30 ones and have them blank, as opposed to adding one at a time and having it map to the ones that have been made.
Right now I just added a for loop so that when the button is clicked, it creates 30 items.
I would really like to know how to skip the add button and creating 30 with it, and just have it automatically populate thirty items with fields.
Or I would also be okay with after the button being pressed, some code causes it to disappear. I have searched all over and while it is easy to make a button get rid of itself in normal code, I can't figure out how to remove a form item from within the form. As far as I know I can't give it a state and manipulate it in the form like with visible false.
If anyone could help me figure out how to make a form.list automatically have 30 items, or how to make a button remove itself (or both) I would greatly appreciate it.
<Form layout="horizontal" onFinish={onFinish} size="medium">
<Form.Item name="building" label="Building">
<Select>
<Option>Building 1</Option>
<Option>Building 2</Option>
</Select>
</Form.Item>
<Form.List name="rooms">
{(fields, { add, remove }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key} style={{ marginBottom: "0px" }}>
<Row gutter={8}>
<Col span={6} key={0}>
<Form.Item
name={[field.name, "room_type"]}
fieldKey={[field.fieldKey, "room_type"]}
>
<Select style={{ marginRight: 8 }}>
<Select.Option key={item} value={item}>
{item}
</Select.Option>
</Select>
</Form.Item>
</Col>
<Col span={6} key={1}>
<Form.Item
name={[field.name, "square_feet"]}
fieldKey={[field.fieldKey, "square_feet"]}
>
<Input />
</Form.Item>
</Col>
<Col span={6} key={2}>
<Form.Item
name={[field.name, "bedroom_num"]}
fieldKey={[field.fieldKey, "bedroom_num"]}
labelCol={{ span: 12 }}
>
<InputNumber />
</Form.Item>
</Col>
<Col span={6} key={3}>
<Form.Item
name={[field.name, "bathroom_num"]}
fieldKey={[field.fieldKey, "bathroom_num"]}
>
<Input />
</Form.Item>
</Col>
<Col span={2} key={4}>
<MinusCircleOutlined
className="dynamic-delete-button"
onClick={() => {
remove(field.name);
}}
/>
</Col>
</Row>
</Form.Item>
))}
<Col span={22} key={2}>
<Form.Item>
<Button
type="dashed"
onClick={() => {
for (var i = 0; i < 30; i++) {
add();
}
}}
>
<PlusOutlined /> Add unit number
</Button>
</Form.Item>
</Col>
</div>
);
}}
</Form.List>
<Form.Item>
<Button type="primary" htmlType="submit">
submit
</Button>
</Form.Item>
</Form>
[1]: https://codesandbox.io/s/antd-reproduction-template-uhu2v?file=/index.js

how to set the state values in react input?

can you please help me how can i show value of state in input field and also input field is editable. i am trying many tricks but not helpful also can't find in Stackoverflow .......................................
I want show brandcode state property "BrandCode" value in input field................................
here is brandcode return values
brandcode : {
BrandCode: "Nick",
BrandID: 1
}
state = {
brandcode: [],
};
Getbrandcode(brandId) {
getBrandCode(brandId)
.then(res => {
debugger;
//console.log(res);
this.setState({
brandcode: res.data.Data // i want show brandcode values in input
});
});
}
``
its a render.....
``
render() {
// const { formikProps} = this.props
return (
<Formik
enableReinitialize={true}
initialValues={this.masterstyledata}
onSubmit={(values, actions) => {
this.onSaveClick(values);
}}
validationSchema={this.validationSchema}
>
{formikProps => (
<>
<Card>
<CardBody>
{this.state.isLoading && <LoadingPanel />}
<Row>
<Col lg={12}>
<Form>
<FormGroup row>
<Label for="Value" sm={3}>Brand</Label>
<Col sm={3}>
<ComboBoxValue
data={this.state.branddesc}
style={{ width: '100%' }}
name="BrandID"
textField="text"
valueField="Value"
dataItemKey="Value"
onChange={(e) => {
this.BrandCodehandleChange(e);
formikProps.setFieldValue("BrandID", e.target.value)
}}
value={formikProps.values.BrandID}
placeholder="Brand Description"
/>
</Col>
</FormGroup>
<FormGroup row>
//here i want set values
<Label for="BrandCode" sm={3}>Style ID</Label>
<Col sm={3}> <Input sm={3}
type="text"
name="BrandCode"
id="BrandCode"
onChange={formikProps.handleChange('MasterStyleCode')}
value={formikProps.values.MasterStyleCode}
placeholder="Enter Style Id"
/>
<Error>{formikProps.errors.MasterStyleCode}</Error>
</Col>
</FormGroup>
</Form>
</Col>
</Row>
</CardBody>
</Card>
you made a mistake in using handleOnChage and onChange, here:
onChange={formikProps.handleChange('MasterStyleCode')}
at render time this function will be executed and the result is undefined (as you know because it's a void function!), and it's not what you want here, to solve this you have to make a HOF and use setFieldValue if your input name is something different than initialValue key which you want to change it, e.g:
onChange={(event) => {
formikProps.setFieldValue('MasterStyleCode', event.target.value)
}}

How to call OnChange function in react using withformik with antd component?

Here I'm calling onChange function on Formik Field but its not calling? How to call custom function on a Formik field?
This is my custom function under React Component:
onStudentScore = (value, form) => {
alert("called");
const maxScore = value.writtenexammaxscore;
console.log(maxScore);
form.getFieldValue("writtenexammaxscore", maxScore);
if (maxScore > form.getFieldValue("writtenexamstudentsscore")) {
alert("MaxScore is less than StudentScore");
}
};
And my Form is created under render and write a onChange function on a StudentScore field. But it's not called? How to call this function?
render() {
const { values, handleSubmit} = this.props
return (
return (
<div>
<h5 align="left">MidTerm Form</h5>
<Card>
<Form onSubmit={handleSubmit}>
<Row>
<Col span={4}>
<b>Written Exam:</b>
</Col>
<Col span={2}>
<Field
name="writtenexammaxscore"
component={AntInput}
type="text"
style={{ width: 40 }}
/>
</Col>
<Col span={2}>outof</Col>
<Col span={3}>
<Field
name="writtenexamstudentsscore"
component={AntInput}
type="text"
style={{ width: 40 }}
onChange={this.onStudentScore}
/>
// I wrote the function on field this way
</Col>
<Col span={2}>
<Divider type="vertical" />
</Col>
</Row>
<Row>
<Col span={10} />
<Col span={8} push={10}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Col>
</Row>
</Form>
</Card>
</div>
);
}
const MidTermForm = withFormik({
mapPropsToValues: () => ({
writtenexammaxscore: '',
writtenexamstudentsscore: '',
oralexammaximumscore: '',
oralexamstudentsscore: '',
}),
handleSubmit(values, { resetForm }) {
resetForm();
console.log(values)
}
})(MidTermFormComponent)
export default MidTermForm
I tried by extending yup validation schema. Instead of calling a function in onChange
check this code sandbox

Resources