I am using AntD select.
When I put select into a separate component, the form does not see the value
Tell me why the form does not receive data on submit ?
Example
const SelectCust = () => {
return (
<Select
mode="multiple"
placeholder="Please select favourite colors"
style={{ width: 500 }}
name="select-multiple"
>
<Option value="red">Red</Option>
<Option value="green">Green</Option>
<Option value="blue">Blue</Option>
</Select>
)};
const Demo = () => {
const onFinish = values => {
console.log("Received values of form: ", values); // {custom:undefined}
};
return (
<Form name="validate_other" onFinish={onFinish}>
<Form.Item name="custom" label="Select custom">
<SelectCust />
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
)};
If you wrap <Select> with <Form.Item> it works correctly:
const SelectCust = () => {
return (
<Form.Item name="custom" label="Select custom">
<Select
mode="multiple"
placeholder="Please select favourite colors"
style={{ width: 500 }}
name="select-multiple"
>
<Option value="red">Red</Option>
<Option value="green">Green</Option>
<Option value="blue">Blue</Option>
</Select>
</Form.Item>
);
};
Here is updated Demo component:
const Demo = () => {
const onFinish = values => {
console.log("Received values of form: ", values);
};
return (
<Form name="validate_other" onFinish={onFinish}>
<SelectCust />
<Form.Item
wrapperCol={{
span: 12,
offset: 6
}}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
EDIT 1
It seemed wrong to me that wrapping <Select> with <Form.Item> solved the problem, so I looked up <Form> documentation.
Here is updated code:
const SelectCust = props => {
return (
<Select
mode="multiple"
placeholder="Please select favourite colors"
onChange={props.onColorChange}
>
<Option value="red">Red</Option>
<Option value="green">Green</Option>
<Option value="blue">Blue</Option>
</Select>
);
};
const Demo = () => {
const [form] = Form.useForm();
const onFinish = values => console.log(values);
const handleColorChanged = value => {
form.setFieldsValue({ custom: value });
};
return (
<Form name="validate_other" form={form} onFinish={onFinish}>
<Form.Item name="custom" label="Select custom">
<SelectCust onColorChange={handleColorChanged} />
</Form.Item>
<Form.Item
wrapperCol={{
span: 12,
offset: 6
}}
>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
Update has 3 important steps:
Add const [form] = Form.useForm() in the beginning of Demo component
Implement handleColorChanged function and pass it as props to SelectCust. Handler sets form value by calling form.setFieldsValue().
Pass from as props to <Form> component
Related
Proper way to do bulk update of documents in react.
I want to bulk update all posts status and type fields in one single query how to achieve it.
Status and Type are dropdown select inputs.
All Posts Component:-
const AllPosts = () => {
const [updateObj ,setUpdateObj] = useState({})
handleUpdate(){
}
return (
<>
<div>
{AllPosts.map((post, index) => (
<Post
key={post._id}
postId={post._id}
postStatus={post.status}
postType={post.type}
postSubject={post.subject}
checked={post?.isChecked || false}
onChange={handleAllChecked}
checkBoxName={post._id}
/>
))}
</div>
</>
);
};
export default AllPosts;
I think I would need an update object which would have post id as key and status and type as its value.
Post component
const Post = ({
postId,
postStatus,
postType,
postSubject,
checked,
onChange,
checkBoxName,
}) => {
return (
<div className="post">
<div className="post-checkbox">
<input
type="checkbox"
id="post-checkbox"
name={checkBoxName}
checked={checked}
onChange={onChange}
/>
</div>
<div>
<div>{postSubject}</div>
<div className="options">
<select onChange={onChange}>
<option>Status A</option>
<option>Status B</option>
<option>Status C</option>
</select>
<select onChange={onChange}>
<option>Type A</option>
<option>Type B</option>
<option>Type C</option>
</select>
</div>
</div>
</div>
);
};
export default Post;
I'm trying to get all selected values from a react-bootstrap Form. On the latest version of bootstrap e.target.value only seems to contain a single value instead of a list when multiple values are selected by shift clicking multiple lines. How can I get all selected values? Preferably by key or id.
const Form = ReactBootstrap.Form;
const Button = ReactBootstrap.Button;
const ExampleForm = () => {
const [output, setOutput] = React.useState("");
function changeSelection(e) {
setOutput(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
}
return(
<Form onSubmit={handleSubmit}>
<Form.Group controlId="dimension">
<Form.Control
as="select"
multiple
onChange={changeSelection}>
<option key="1" id="1" >1</option>
<option key="2" id="2" >2</option>
<option key="3" id="3" >3</option>
<option key="4" id="4" >4</option>
</Form.Control>
<Button type="submit" variant="primary">
select
</Button>
</Form.Group>
Output: {output}
</Form>
);
}
ReactDOM.render(
<ExampleForm />,
document.getElementById('app')
);
Codepen example can be found here
Turns out you can use Array.from
Array.from(e.target.selectedOptions, option => option.value)
Found here
I want to retrieve the value from my selection so I can make post requests. I have no problem getting from text input, but for some reason I can't get it from the drop down menu select. I end up getting a
"TypeError: Cannot read property 'value' of undefined"
Here is the code I am using.
import React from "react";
import { Form, Input, Button, Select } from "antd";
const { Option } = Select;
class ItemForm extends React.Component {
handleFormSubmit = event => {
event.preventDefault();
const name = event.target.elements.name.value;
const description = event.target.elements.description.value;
const category = event.target.elements.category.value;
console.log(name, description, this.refs.category.value);
};
render() {
return (
<div>
<Form onSubmit={this.handleFormSubmit}>
<Form.Item label="Form Layout" />
<Form.Item label="Product Name">
<Input name="name" placeholder="Ex: Organic Apple..." />
</Form.Item>
<Form.Item label="Description">
<Input name="description" placeholder="Ex: Juicy organic apples!" />
</Form.Item>
<Form.Item label="Category">
<Select name="category" placeholder="Please select a category">
<Option value="Fruit">Fruit</Option>
<Option value="Vegetable">Vegetable</Option>
<Option value="Poultry">Poultry</Option>
</Select>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
</div>
);
}
}
export default ItemForm;
Use onChange which is fired when the value of the select changes. antd select documentation
<Form.Item label="Category">
<Select
onChange={(value) => {
alert(value)
}}
name="category"
placeholder="Please select a category">
<Option value="Fruit">Fruit</Option>
<Option value="Vegetable">Vegetable</Option>
<Option value="Poultry">Poultry</Option>
</Select>
</Form.Item>
working example
Something similar to the classic javascript approach, you intended to use, could be use getFieldValue.
But coupling to coherent createRef , Form and Form.Item as below.
When getting values, remember to reference the Form.Item name and not the Input one ;-)
I have created a sandbox demo hoping other people will enjoy or contribute.
import React from "react";
import { Form, Input, Button, Select } from "antd";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css"; //export default ItemForm;
const { Option } = Select;
class ItemForm extends React.Component {
formRef = React.createRef();
handleFormSubmit = event => {
event.preventDefault();
console.log("All field values", this.formRef.current.getFieldsValue());
const name = this.formRef.current.getFieldValue("productName"); //OLD event.target.elements.name.value;
const description = this.formRef.current.getFieldValue("description"); //OLD event.target.elements.description.value;
const category = this.formRef.current.getFieldValue("category"); //OLD event.target.elements.category.value;
console.log(name, description, category);
alert(`${name}, ${description}, ${category}`);
};
render() {
return (
<div>
<Form ref={this.formRef} onSubmit={this.handleFormSubmit}>
<Form.Item label="Form Layout (Form.Item-createRef-getFieldValue Example)" />
<Form.Item label="Product Name" name="productName">
<Input name="name" placeholder="Ex: Organic Apple..." />
</Form.Item>
<Form.Item label="Description" name="description">
<Input name="description" placeholder="Ex: Juicy organic apples!" />
</Form.Item>
<Form.Item label="Category" name="category">
<Select name="category" placeholder="Please select a category">
<Option value="Fruit">Fruit</Option>
<Option value="Vegetable">Vegetable</Option>
<Option value="Poultry">Poultry</Option>
</Select>
</Form.Item>
<Form.Item>
<Button
type="primary"
htmlType="submit"
onClick={this.handleFormSubmit}
>
Submit
</Button>
</Form.Item>
</Form>
</div>
);
}
}
ReactDOM.render(<ItemForm />, document.getElementById("container"));
Managed it by using onChange as shown below this.
state = {
status: ""
};
<Form.Item label="Status">
<Select
name="status"
onChange={value => {
this.setState({ status: value });
}}
placeholder="Please choose the status"
>
<Option value="new">New</Option>
<Option value="open">Open</Option>
<Option value="rejected">Rejected</Option>
<Option value="deferred">Deferred</Option>
<Option value="reopened">Reopened</Option>
</Select>
</Form.Item>
unlike what you would expect, in Ant Design Select you can't get the value by calling:
onChange={(e)=>console.log(e.target.value)}
no. instead you get the value directly by just accessing the event itself, like this:
onChange={(e)=>console.log(e)}
You can fix this as follows. (Works fine for Antd)
<Select
onChange={(text, index) => {
console.log(index.children);
}}
>
A better and cleaner way to avoid this issue is to define all the form values and labels in an array and pass it into the . Declare or use an onChange event and store the value of the event in your state.
I follow to this code:
import React from 'react';
import { Formik, Form, Field, FieldArray } from 'formik';
// 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: ['jared', 'ian', 'brent'] }}
onSubmit={values =>
setTimeout(() => {
alert(JSON.stringify(values, null, 2));
}, 500)
}
render={({ values }) => (
<Form>
<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>
))
) : (
<button type="button" onClick={() => arrayHelpers.push('')}>
{/* show this when user has removed all friends from the list */}
Add a friend
</button>
)}
<div>
<button type="submit">Submit</button>
</div>
</div>
)}
/>
</Form>
)}
/>
</div>
);
But that for text input Field.
I want to replace to select and I do something like that.
Replace:
<Field name={`issues.${index}`} />
To:
<Field component="select" name="color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</Field>
I add 3 component when I choose the value in one component, It's effect to all of the component.
What did I wrong here?
The name property for each select input needs to be unique. Try the following
<Field component="select" name={`friends.${index}`}>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</Field>
I'm trying to get the value of an option inside my select in React.js but somehow e.value is always undefined.
This is the code:
<Col md={4} className="col-padding-left">
<Input onChange={this.filterProducts} type="select" name="select" id="exampleSelect">
<option name='default'>Default</option>
<option name='price' value='desc'>Price (High-Low)</option>
<option name='price' value='asc'>Price (Low-High)</option>
<option name='addedAt' value='desc'>Added At (First-Last)</option>
<option name='addedAt' value='asc' >Added At (Last-First)</option>
<option name='name' value='desc'>Name (A-Z)</option>
<option name='name' value='asc'>Name (Z-A)</option>
</Input>
</Col>
With the following function filterProducts:
filterProducts(e){
console.log(e.value);
}
Try this
<Col md={4} className="col-padding-left">
<Input onChange={this.filterProducts.bind(this)} type="select" name="select" id="exampleSelect">
<option name='default'>Default</option>
<option name='price' value='desc'>Price (High-Low)</option>
<option name='price' value='asc'>Price (Low-High)</option>
<option name='addedAt' value='desc'>Added At (First-Last)</option>
<option name='addedAt' value='asc' >Added At (Last-First)</option>
<option name='name' value='desc'>Name (A-Z)</option>
<option name='name' value='asc'>Name (Z-A)</option>
</Input>
</Col>
filterProducts = (e) => {
console.log(e.target.value);
}
You need to use e.target.value
See this question: OnChange event using React JS for drop down
First, check if you have e. If so, try e.target.value.
The event object doesn't hold a value property.
In order to access the value attribute of element you need to use event.target.value when target is the element that triggered this event.
Running example:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
items: ['john', 'jane', 'greg']
};
}
onSelect = e => {
console.log(e.target.value);
}
render() {
const{items} = this.state;
return (
<div>
<select onChange={this.onSelect}>
{
items.map(item => {
return (<option value={item}>{item}</option>)
})
}
</select>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
According to your request, it's my solution:
<Col md={4} className="col-padding-left">
<Input onChange={this.filterProducts} type="select" name="select" id="exampleSelect">
<option name='default'>Default</option>
<option name='price' value='desc'>Price (High-Low)</option>
<option name='price' value='asc'>Price (Low-High)</option>
<option name='addedAt' value='desc'>Added At (First-Last)</option>
<option name='addedAt' value='asc' >Added At (Last-First)</option>
<option name='name' value='desc'>Name (A-Z)</option>
<option name='name' value='asc'>Name (Z-A)</option>
</Input>
</Col>
The function for could be:
filterProducts(e){
// e.target.id identified the unique element in DOM
// in example when 'exampleSelect' make a change (onChange) event
if(e.target.id === 'exampleSelect'){
console.log("Value for exampleSelect: " + e.target.value);
}
// if you have another html input select add here another 'if'
// with a diferent id. ex.
if(e.target.id === 'fruitSelect'){
console.log("Value for fruit: " + e.target.value);
}
...
}
¡Ey!, don't forget to bind the function, in the React constructor:
this.filterProducts = this.filterProducts.bind(this);