How to get selected value in dropdown using Formik Field in React JS? - reactjs

export class SelectFruitModal extends Component {
FruitList = ['Apple', 'Mango', 'Chickoo', 'others'];
FruitListItems = this.FruitList.map((fruit) => <option key={fruit}>{fruit}</option>);
handleChange(event){
alert('Event',event.target.value)
}
render() {
return (
<div>
<Modal>
<ModalBody>
<Formik
initialValues={{
FruitList: ''
}}
render={({}) =>
!isSubmitting ? (
<div>
<Row>
<Form>
<Row>
<Col>
<div className="form-group">
<Field
name="FruitList"
component="select"
className={
'form-control' +
(errors.FruitList &&
touched.FruitList
? ' is-invalid'
: '')
}
onChange={this.handleChange}
>
<option disabled="disabled" value="">
Select fruit
</option>
{this.FruitListItems}
</Field>
</div>
</Col>
</Row>
</Form>
</Row>
</div>
) : (
<PageSpinner />
)}
/>
</ModalBody>
</Modal>
</div>
);
}
}
export default SelectFruitModal;
1.In above code I have dropdown of FruitList
2.My requirement is when I select others value from the fruitlistItems then I should get one textArea beside it.
3.For that I need to get selected value from dropdown as 'others' so that i can enable field textbox.
4.How can I get selected value of dropdown ? I tried using onChange() and calling event value in it gives me empty value. Please help?

Related

How to dynamically create a form that adds dynamic fields and nested array using the formik fieldArray

I am trying to create dynamic form with fieldArray in react. My code looks like this
<Formik initialValues={{
data:[],
}}
onSubmit={(values)=>{
console.log(values)
}}
>
{
(formik)=>(
<Form>
<h2>form starts here</h2>
<FieldArray name='data' render={
(arrayHelpers)=>{
return(
<div>
<button type='button' onClick={()=>arrayHelpers.insert(formik.values.data.length + 1,{question:'',quesType:'',answers:['']})}>Add</button>
{/* starts */}
{formik.values.data.map((d,index)=>(
<div key={index}>
<label htmlFor={`data.${index}.question`}>question</label>
<Field name={`data.${index}.question`} type='text' id={`data.${index}.question`}/>
<label htmlFor={`data.${index}.quesType`}>quesType</label>
<Field as="select" name={`data.${index}.quesType`}>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</Field>
</div>
// end
))}
</div>
);
}
}/>
<button type='submit'>submit</button>
</Form>
)
}
</Formik>
so after clicking add button my initialValue looksLike
data[{question:'',questype:'',answers:[]}]
Now after the select option I want to add a button that will add values in the answers array. I tried looping the d.answers but the answers property was not accessible even though I have the property. So, How to achieve this? Thanks in advance!

Need to do Radio button in antd default checked

I have a Radio Button Group with dynamically data coming from an array.
Here's the code :
<Radio.Group
options={uniqueRadioElements}
onChange={onCategorySelect}
value={selectedCategory}
optionType="button"
buttonStyle="solid"
className="select-category"
checked="true"
/>
<Col span={24}>
<div className="professionals-wrapper">
{arrayOfElements
.filter((item) => item.category === selectedCategory)
.map((item) => {
return (
<div className="details-of-categories">
<Image
src="/images/clinic.png"
preview={false}
alt="photo 4"
/>
<h3>{item.title}</h3>
<Rate defaultValue={4} disabled />
</div>
)
})}
</div>
</Col>
I want to make it default checked for a specific element of Radio Button Group
You can add the prop defaultChecked to the specific index you want. An example for the first one would be:
<input defaultChecked={index === 0} />
In your case I would delete the checked value and add the defaultChecked.
<Radio.Group
options={uniqueRadioElements}
onChange={onCategorySelect}
value={selectedCategory}
optionType="button"
buttonStyle="solid"
className="select-category"
defaultChecked={index === 0} />

Dynamic Form with initial values

Sorry for my english.
Like in this example
https://codesandbox.io/s/wonderful-lichterman-br63z?file=/index.js
Form.List is rendering the Array of "Fields" which initally is empty.
I would like to put my own array to be rendered from the start.
Expected result
you can do it using initialValues prop of Form.
Working example: https://codesandbox.io/s/bold-turing-g8ft6?file=/index.js
Docs: https://ant.design/components/form/#API
The docs are a bit short on explanation for the Form.List, and since a code sample is worth a thousand words...
This renders the dynamic form list with one item already visible:
const initialValues = {
users: [
{ age: undefined } // undefined will render the placeholder
]
};
<Form initialValues={initialValues}>
<Form.List name="users">
{(fields, { add }) => {
return (
<div>
{fields.map(field => (
<Row key={field.key}>
<Col>
<Form.Item
placeholder="age"
name={[field.age, 'age']}
>
<Input />
</Form.Item>
</Col>
<Col>
<Form.Item
placeholder="sex"
name={[field.sex, 'sex']}
>
<Input />
</Form.Item>
</Col>
<Col>
<Form.Item
placeholder="name"
name={[field.name, 'name']}
>
<Input />
</Form.Item>
</Col>
</Row>
))}
<button onClick={() => add()}>Add</button>
</div>
)
}}
</Form.List>
</Form>

How to get values from react FieldArray in formik form with other fields?

I have created a Formik form that contains a field array, form and fieldArray is in two separate classes as separate components.
My form:
<Formik onSubmit = {(values, { setSubmitting }) => { setSubmitting(false);}}
enableReinitialize>
{({handleSubmit, errors})=> (
<Form onSubmit= { handleSubmit }>
<Form.Group as= { Row } controlId= "cpFormGroupTitle" className="required">
<Form.Label className="post-create-label" column sm={ 2 } >
Title
</Form.Label>
<Col sm={ 10 }>
<Field name="title" component={ renderTextField } type="text"
isinvalid={ !!errors.title ? "true": "false" }
placeholder="Title *" />
</Col>
</Form.Group>
<Form.Group as= { Row } controlId= "cpFrmGroupShortDesc" className="required">
<Form.Label className="post-create-label" column sm={ 2 } >
Short Description
</Form.Label>
<Col sm={ 10 }>
<Field name="short-desc" component={ renderTextArea } type="text"
isinvalid={ !!errors.shortDescription ? "true": "false" }
placeholder="Short Description *" />
</Col>
</Form.Group>
<Form.Group as= { Row } controlId= "cpFormGroupFeatures">
<Form.Label className="post-create-label" column sm={ 2 }>
Features
</Form.Label>
<Col sm={ 10 }>
<TextFieldArray initialValues={{ features: [] } } name="features"/>
</Col>
</Form.Group>
<Form.Group as={ Row }>
<Col sm= { { span: 2, offset:2 } }>
<Button type="submit" variant="primary">Submit</Button>
</Col>
<Col sm={ 2 }>
<Button variant="secondary">Save as draft</Button>
</Col>
</Form.Group>
</Form>
)}
</Formik>
Here, <TextFieldArray> is field array , I need to get values from field array when form is submitted.
TextFieldArray:
export const TextFieldArray = (props) => (
<React.Fragment>
<Formik initialValues= { props.initialValues } render={({ values }) => (
<Form>
<FieldArray name= { props.name } render={arrayHelper => (
<div>
{ values[props.name] && values[props.name].length > 0 ?
(
values[props.name].map((item, index) => (
<div key={index}>
<Form.Group as= { Row }>
<div className="col-md-8">
<Field name={`${props.name}.${index}`}
className="form-control"/>
</div>
<div className="col-md-2">
<Button type="button" variant="outline-secondary"
onClick={() => arrayHelper.remove(index)}>
Remove
</Button>
</div>
<div className="col-md-2">
<Button type="button" variant="outline-secondary"
onClick={() => arrayHelper.insert(index, '')}>
Add
</Button>
</div>
</Form.Group>
</div>
))
) : (
<Button type="button" variant="outline-secondary"
onClick={() => arrayHelper.push('')} >
{`Add ${ props.name }`}
</Button>
)
}
</div>
)} />
</Form>
)} />
</React.Fragment>
);
I'm a beginner to ReactJS, so someone help me please, that will be huge help from you all.
Thanks.
To have field array be part of same form as other fields, only have one <Formik> and one <Form>. Then make initialValues on Formik that describes all the fields:
<Formik
initialValues={{ friends: someFriends, random: randomText }}
As seen in the following code from Formik FieldArray docs, with another form field added that is not part of the array:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Formik, Form, Field, useField, FieldArray } from "formik";
const someFriends = ["jared", "ian", "brent"];
const randomText = "Four score and seven years ago...";
function MyTextInput({ label, ...props }) {
// useField() returns [formik.getFieldProps(), formik.getFieldMeta()]
// which we can spread on <input> and alse replace ErrorMessage entirely.
const [field, meta] = useField(props);
return (
<>
<label
htmlFor={props.id || props.name}
css={{ backgroundColor: props.backgroundColor }}
>
{label}
</label>
<input className="text-input" {...field} type="text" {...props} />
{meta.touched && meta.error ? (
<div className="error">{meta.error}</div>
) : null}
</>
);
}
// Here is an example of a form with an editable list.
// Next to each input are buttons for insert and remove.
// If the list is empty, there is a button to add an item.
export const FriendList = () => (
<div>
<h1>Friend List</h1>
<Formik
initialValues={{ friends: someFriends, random: randomText }}
onSubmit={values =>
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500)
}
render={({ values }) => (
<Form>
<MyTextInput label="Random comment" name="random" />
<FieldArray
name="friends"
render={arrayHelpers => (
<div>
{values.friends &&
values.friends.length > 0 &&
values.friends.map((friend, index) => (
<div key={index}>
<Field name={`friends.${index}`} />
<button
type="button"
onClick={() => arrayHelpers.remove(index)} // remove a friend from the list
>
-
</button>
<button
type="button"
onClick={() => arrayHelpers.insert(index, "")} // insert an empty string at a position
>
+
</button>
</div>
))}
{/* Add a new empty item at the end of the list */}
<button type="button" onClick={() => arrayHelpers.push("")}>
Add Friend
</button>
<div>
<button type="submit">Submit</button>
</div>
</div>
)}
/>
</Form>
)}
/>
</div>
);
ReactDOM.render(<FriendList />, document.getElementById("root"));
Code in codesandbox.
I don't think you need to create second form for child component.
You need to just pass the values from the parent to the TextFieldArray
<TextFieldArray values={values.myArr} name="features"/>
And the child component just receive the values and render them (as if it was in the parent component)
export const TextFieldArray = (props) => {
return (
<React.Fragment>
<FieldArray
name= { props.name }
render={arrayHelper => (
<div>
{
props.values[props.name] && props.values[props.name].length > 0 ?
(
props.values[props.name].map((item, index) => (
<div key={index}>
<Form.Group as= { Row }>
<div className="col-md-8">
<Field name={`${props.name}.${index}`} className="form-control"/>
</div>
<div className="col-md-2">
<Button type="button" variant="outline-secondary"
onClick={() => arrayHelper.remove(index)}>
Remove
</Button>
</div>
<div className="col-md-2">
<Button type="button" variant="outline-secondary"
onClick={() => arrayHelper.insert(index, '')}
>
Add
</Button>
</div>
</Form.Group>
</div>
))
) : (
<Button type="button" variant="outline-secondary" onClick={() => arrayHelper.push('')} >
{`Add ${ props.name }`}
</Button>
)
}
</div>
)}
/>
</React.Fragment>
)
Of course don't forget to add the initial values of the array to the parent component.
And finally when you click on the submit button it would give you the values.

Using props inside of a field-array in redux-from

I have a redux-form stateless component that contains a field array. I'm trying to determine how to pass a prop to a contained field in order to populate select list options.
const renderSoftwareForm = ({ fields, meta: { error, submitFailed }, props}) => (
<ul style={{listStyle: "none", padding: "0"}}>
<li>
<button type="button" onClick={() => fields.push({})}>
Add Line Item
</button>
</li>
{fields.map((softwares, index) => (
<li key={index}>
<Row>
<Col sm={1}>
<Field
label="Theme"
name={`${softwares}.theme`}
type="select"
component={SelectComponent}
>
<option>test</option>
{props.themes.data && props.themes.data.map(themes => (
<option value={themes.prodLine} key={themes.prodLineId}>
{themes.prodLine}
</option>
))}
</Field>
</Col>
</Row>
<div style={{textAlign: "center"}}>
<button type="button" onClick={() => fields.remove(index)}>
Remove Line Item
</button>
</div>
<div>
<span> </span>
</div>
</li>
))}
</ul>
)
const SoftwareForm = props => {
const { handleSubmit, pristine, reset, submitting } = props
return (
<div>
<FieldArray name="softwares" props={props} component={renderSoftwareForm} />
</div>
)
}
export default SoftwareForm;
Everything works with static values in the options list.
I can see the props being passed all the way to renderSoftwareForm, but it doesn't seem to be available inside of my Field... I feel like I'm missing something easy... props.themes.data returns an error --- Cannot read property 'themes' of undefined ---... How do I access this prop in the FieldArray Field?
Thanks!
<Field
label="Theme"
name={`${softwares}.theme`}
type="select"
component={SelectComponent}
props={{
themes: props.themes
}}
>
<option>test</option>
{props.themes.data && props.themes.data.map(themes => (
<option value={themes.prodLine} key={themes.prodLineId}>
{themes.prodLine}
</option>
))}
</Field>
This way themes props will be avaiilable in you selectComponent

Resources