I'm a beginner in React and I was following a tutorial on how to create a React app with Django backend.In the video he uses Ant Design Components v3(that was the latest when the video was made). Now I'm using the latest one v4 and they changed the form onSubmit to onFinish. After some research in the comments, people posted about the update and how to make it work but no luck.The problem is that I'm trying to get the data from the form inputs(title and content) and it shows undefined.Any ideas?
Here is the component:
import React, { Component } from "react";
import { Form, Input, Button } from "antd";
const FormItem = Form.Item;
class CustomForm extends Component {
handleFormSubmit = (values) => {
const title = values.title;
const content = values.content;
console.log(title, content, values);
};
render() {
return (
<div>
<Form onFinish={(values) => this.handleFormSubmit(values)}>
<FormItem label="Title">
<Input name="title" placeholder="Article Content" />
</FormItem>
<FormItem label="Content">
<Input
name="content"
placeholder="Enter Article Content"
/>
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
Submit
</Button>
</FormItem>
</Form>
</div>
);
}
}
export default CustomForm;
And the output of the console.log() is:
undefined, undefined, {}
It's because Form.Item or, in your case, FormItem, must have a name prop which is missing so values are not being saved against that key, so e.g.
Change this:
<FormItem label="Title">
<Input name="title" placeholder="Article Content" />
</FormItem>
To
<FormItem label="Title" name="title">
<Input placeholder="Article Content" />
</FormItem>
Here is what i use instead of onSubmit for antd 4.x.x Form:
import React from 'react';
import { Form, Input, Button } from 'antd';
const FormItem = Form.Item;
class CustomForm extends React.Component {
handleFormSubmit = (values) => {
const title = values.title;
const content = values.content;
console.log(title, content);
};
render(){
return (
<div>
<Form onFinish={(values) => this.handleFormSubmit(values)}>
<FormItem label="Title" name="title">
<Input placeholder="Put a title here" />
</FormItem>
<FormItem label="Content" name="content">
<Input placeholder="Enter some content ..." />
</FormItem>
<FormItem >
<Button type="primary" htmlType="submit">Submit</Button>
</FormItem>
</Form>
</div>
);
}
}
export default CustomForm;
Related
How can I define input attributes in typescript? I have an AddUser Component and TextInput Component, I want to import the TextInput component inside the AddUser component and then pass props to the TextInput component.
AddUser.tsx
import Button from '../Shared/Form/Button/Button';
import Form from '../Shared/Form/Form';
import TextArea from '../Shared/Form/TextArea/TextArea';
import TextInput from '../Shared/Form/TextInput/TextInput';
const AddUser = () => {
return (
<div>
<h1>Add User</h1>
<Form method="post" className={'user-form'}>
<TextInput label={'Name'} type="text" name="name" required />
<TextInput label={'Email'} type="email" name="email" required />
<TextInput label={'Country'} type="text" name="country" required />
<TextInput label={'Phone'} type="text" name="phone" required />
<TextArea label={'Address'} name="address" cols="30" rows="4" />
<div className="form-button">
<Button type={'submit'} className={'btn-add'}>
Add
</Button>
<Button type={'submit'} className={'btn-close'}>
Cancel
</Button>
</div>
</Form>
</div>
);
};
export default AddUser;
TextInput.tsx
const TextInput = ({ className, label, ...rest }: { className: string; label: string }) => {
return (
<div className={`${className} form-field`}>
<label htmlFor={label}>{label}</label>
<input {...rest} />
</div>
);
};
export default TextInput;
You can extend HTMLProps which comes with react:
import { HTMLProps } from "react";
interface MyCOmponentProps extends HTMLProps<HTMLInputElement> {
{...}
}
This is how we can make a reusable component. maybe I missed something in onChangeAction according to type script. please let me know me in the comment section so that i can help you better
Example codesandbox
const AddUser = () => {
return (
<div>
<h1>Add User</h1>
<form method="post" className={"user-form"}>
<TextInput
label={"Name"}
placeholder="Name"
type="text"
name="name"
required
/>
<TextInput
label={"Email"}
placeholder="Email"
type="email"
name="email"
required
/>
<TextInput
label={"Country"}
placeholder="Country"
type="text"
name="country"
required
/>
<TextInput
label={"Phone"}
placeholder="Phone"
type="text"
name="phone"
required
/>
</form>
</div>
);
};
export default AddUser;
const TextInput = ({
className,
label,
value,
type,
onChangeAction,
placeholder
}) => {
return (
<div className={`${className} form-field`}>
<label htmlFor={label}>{label}</label>
<input
placeholder={placeholder || "Text"}
type={type || "text"}
value={value}
onChange={onChangeAction}
/>
</div>
);
};
when I click on the submit button on react js, Submit doesn't work, I don't know why?
I'm using ant.design Ui component in on backend Using Django python.
import React from "react";
import { Form, Input, Button } from "antd";
const FormItem = Form.Item;
class ExtrashiftForm extends React.Component {
handleFormSubmit = (event) => {
event.preventDefault();
const title = event.target.elements.title.value;
const manager = event.target.elements.manager.value;
const gender = event.target.elements.gender.value;
const Lable = event.target.elements.Lable.value;
const datetime = event.target.elements.datetime.value;
console.log(title, manager,gender,Lable,datetime);
};
render() {
return (
<div>
<Form onSubmit={this.handleFormSubmit}>
<FormItem name="title" label="Title">
<Input placeholder="title here" />
</FormItem>
<FormItem name="manager" label="Manager">
<Input placeholder="select Manager Name .. " />
</FormItem>
<FormItem name="gender" label="Gender">
<Input placeholder="select Gender Type .. " />
</FormItem>
<FormItem name="Lable" label="Lable">
<Input />
</FormItem>
<FormItem name="datetime" label="DateTime">
<Input />
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit">
Ok
</Button>
</FormItem>
</Form>
</div>
);
}
}
export default ExtrashiftForm;
this part of code included inside the layout page, and all text coming but when I check Console in chrome browser, didn't send any data to console.
please help me, thank you
Change onSubmit to onFinish.
onFinish cb will have values as object. That also need to update.
<Form onFinish={(values) => console.log(values)}>
or
<Form onFinish={({title, manager,gender,Lable,datetime}) => console.log({title, manager,gender,Lable,datetime})}>
Try this one
<Form onFinish={(values) => this.handleFormSubmit(values)}>
<FormItem label="Title">
<Input placeholder="title here" name="title" />
</FormItem>
</Form>
const handleFormSubmit = (values) => {
const title = values.title;
console.log(title);
};
I want to show all the details filled in the html form on another page using react js. I have created the html form which is the landing page. And after clicking on submit all the information should be displayed on another page.
My form.js page for creating the html form
import React, { component } from 'react';
var details = () => {
return(
<div>
<form>
Name: {" "}
<input type="text" placeholder="Enter name" /><br />
Contact No.: {" "}
<input type="number" placeholder="Enter contact number" />
<br />
<input type="submit" value="submit"/>
</form>
</div>
);
}
export default details;
My app.js page
import React from 'react';
import logo from './logo.svg';
import './App.css';
import Details from './form/form';
function App() {
return (
<div className="App">
<header className="App-header">
<Details />
</header>
</div>
);
}
export default App;
The data which you'll store in react state will be in browser memory and on refresh you'll lose that data.
In case, If you want functionality like the preview on form submit then you can store data in state and show/hide the preview on form submit.
So, Basically you can use state or some third party state management library to store the data. Here is a basic example of how you can achieve in the same details component.
import React, { useState } from 'react';
const Details = () => {
const [name, setName] = useState('');
const [number, setNumber] = useState(null);
const [showPreview, setShowPreview] = useState(false);
return(
<div>
{!showPreview && <form onSubmit={e => e.preventDefault()}>
Name: {" "}
<input type="text" placeholder="Enter name" onChange={e => setName(e.target.value)} /><br />
Contact No.: {" "}
<input type="number" placeholder="Enter contact number" onChange={e => setNumber(e.target.value)} />
<br />
<input type="button" value="submit" onClick={() => setShowPreview(!showPreview)}/>
</form>}
{showPreview && (<div>
<p>{name}</p>
<p>{number}</p>
</div>)}
</div>
);
}
export default Details;
Again, This answer is based on lots of assumptions. Maybe we need some more details in the question to have a precise answer.
In case if you want to display the same data on any other page then you can use Redux. Which can store the data in the redux store and you display the same data on another page.
First, on the app we want to create a function that can receive the data, then send it to the component as a prop:
import React from 'react';
import Details from './form';
function App() {
const getFormData = function (name, number) {
console.log('Name: ', name, 'Number: ', number)
}
return (
<div className="App">
<header className="App-header">
<Details sendFormData={getFormData} />
</header>
</div>
);
}
export default App
Then, inside the component you want to set each input to update their state as they change. When you click submit, you pass the state to the up to the app components getFormData function.
import React, { useState } from 'react';
const Details = (props) => {
const [userName, setName] = useState('');
const [userNumber, setNumber] = useState('');
const handleSubmit = () => {
props.sendFormData(userName, userNumber)
}
return (
<div>
Name: {" "}
<input type="text" placeholder="Enter name"
onChange={event => setName(event.target.value)} /><br />
Contact No.: {" "}
<input type="number" placeholder="Enter contact number"
onChange={event => setNumber(event.target.value)} />
<br />
<button onClick={() => handleSubmit()} >Submit</button>
</div>
);
}
export default Details;
I am working with redux-form. I need to create a new user and update the user's information using the same form. I've made the required form to create a new user right now, but I don't know how to make it available for updating.
Form Component code:
class UserRegistrationForm extends PureComponent {
static propTypes = {
handleSubmit: PropTypes.func.isRequired,
reset: PropTypes.func.isRequired,
isLoading: PropTypes.bool,
submitting: PropTypes.bool.isRequired,
};
constructor() {
super();
this.state = {
showPassword: false,
};
}
showPassword = (e) => {
e.preventDefault();
this.setState(prevState => ({ showPassword: !prevState.showPassword }));
};
onSubmit = data => {
console.log(data);
}
render() {
const { handleSubmit, reset } = this.props;
return (
<Col md={12} lg={12}>
<Card>
<CardBody>
<div className="card__title">
<h5 className="bold-text">STUDENT INFORMATION</h5>
</div>
<form className="form form--horizontal" onSubmit={handleSubmit}>
<div className="form__form-group">
<span className="form__form-group-label">First Name*</span>
<div className="form__form-group-field">
<Field
name="name"
component="input"
type="text"
placeholder="Name"
/>
</div>
</div>
<div className="form__form-group">
<span className="form__form-group-label">Last Name*</span>
<div className="form__form-group-field">
<Field
name="surname"
component="input"
type="text"
placeholder="Surname"
/>
</div>
</div>
<div className="form__form-group">
<span className="form__form-group-label">E-mail*</span>
<div className="form__form-group-field">
<Field
name="email"
component="input"
type="email"
placeholder="example#mail.com"
/>
</div>
</div>
<ButtonToolbar className="form__button-toolbar">
<Button color="primary" type="submit" className="icon" size="sm"><SendIcon /> Submit</Button>
<Button type="button" onClick={reset} className="icon" size="sm">
<CloseIcon /> Cancel
</Button>
</ButtonToolbar>
</form>
</CardBody>
</Card>
</Col>
);
}
}
export default reduxForm({
validate,
form: 'User_Registration_Form', // a unique identifier for this form
})(withTranslation('common')(UserRegistrationForm));
How can I make the form both available creating and updating?
To use the same form for the update as well, you would need to give an initialValues state to Form. Where initial values would be the value of the student you want to edit. Initialize values would be empty when you are creating a new student.
UserRegistrationForm = reduxForm({
validate,
form: 'User_Registration_Form', // a unique identifier for this form
})(withTranslation('common')(UserRegistrationForm));
InitializeFromStateForm = connect(
state => ({
initialValues: studentData
}),
)(InitializeFromStateForm)
export default UserRegistrationForm
An example is here https://redux-form.com/6.6.3/examples/initializefromstate/
Also in your react route file, try to maintain two routes with the same form component.
<Route path="/student/create" component={UserRegistrationForm} />
<Route path="/student/update/:id" component={UserRegistrationForm} />
So whenever you need to create, you redirect to create route and when you need to update, redirect it to update route, with an id as params.
Just created this form as part of a tutorial. However, my console log is giving me undefined whenever I submit the form. What am I doing wrong?
import React, {Component} from 'react';
import { reduxForm } from 'redux-form';
class Signin extends Component {
handleFormSubmit({email, password}) {
console.log(email); // this gives me 'undefined'
}
render() {
const {handleSubmit, fields: {email, password}} = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Email:</label>
<input {...email} className="form-control" />
</fieldset>
<fieldset className="form-group">
<label>Password:</label>
<input {...password} className="form-control" />
</fieldset>
<button action="submit" className="btn btn-primary">Sign in</button>
</form>
);
}
}
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);
This is due to an update to redux-form.
Rather than importing the values of {email, password} from this.props we instead use a Field component imported from redux-form.
import { Field, reduxForm } from 'redux-form';
Then using it in place of the input tag you have:
<fieldset className="form-group">
<label>Email:</label>
<Field
name="email"
className="form-control"
component="input"
type="text"
placeholder="Email"
/>
</fieldset>
The connection of this input to redux-form now comes from the name property instead of extracting it from this.props
Important to note: that the name MUST be the same as the name in the fields: [] array defined in the reduxForm:
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);
Building on this, if you want to customise the component that the Field uses, you can define your own custom component pretty easily.
Instead of supplying a string to Field's component property, you can define a function:
<div className="form-group">
<label>Last name:</label>
<Field type="text" className="form-control" placeholder="Smith" name="lastName"
component={textField} />
</div>
textField is imported from another file: import {textField} from '../../redux_form_elements';
And textField is as follows:
import React from 'react';
export const textField = (field) => (
<div>
<input className="form-control" {...field.input} type={field.type} placeholder={field.placeholder} />
{field.meta.touched && field.meta.error &&
<label id="basic-error" className="validation-error-label">This field is required.</label>
}
</div>
);
This looks like the Grider Tutorial. I fixed it this way, with a renderInput function which takes the field. Not sure if this is useful for you.
import React, {Component} from 'react';
import { reduxForm } from 'redux-form';
import { Field } from 'redux-form';
const renderInput = field => (
<div>
<input {...field.input} type={field.type} className="form-control" />
{field.meta.touched && field.meta.error}
<span>{field.meta.error}</span>
</div>
);
class Signin extends Component {
handleFormSubmit({email, password}) {
console.log(email);
console.log("Hi");
}
render() {
const {handleSubmit, fields: {email, password}} = this.props;
return (
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
<fieldset className="form-group">
<label>Email</label>
<Field
name="email"
component={renderInput}
type="text" />
</fieldset>
<fieldset className="form-group">
<label>Password</label>
<Field
name="password"
component={renderInput}
type="text" />
</fieldset>
<button action="submit" className="btn btn-primary">Sign in</button>
</form>
);
}
}
export default reduxForm({
form: 'signin',
fields: ['email', 'password']
})(Signin);