How to make form component submit using button in form? - reactjs

I have the following code where a text input box accepts an url and if it is valid it should create a display area and provide a nice preview of the url.
But I am not sure how to associate the submit from the button with the submit from the form.
import React, {useState} from 'react';
import './App.css';
import Microlink from '#microlink/react';
import { String } from 'core-js';
import Card from '#material-ui/core/Card';
import TextField from '#material-ui/core/TextField';
import Button from "#material-ui/core/Button";
function validURL(str) {
var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locator
return !!pattern.test(str);
}
function App (){
const [myurl, setMyurl] = useState("")
const [display, setDisplay] = useState(true)
const handleChange = (event) => {
const url = event.target.value
var str = validURL(url)
console.log(str)
str ? setMyurl(String(url)) : setDisplay(false)
}
return (
<form>
<TextField
id="outlined-name"
label="Name"
margin="normal"
variant="outlined"
onSubmit={event => handleChange(event)}
/>
<Button
type="submit"
variant="contained"
>
Submit
</Button>
{display ?
<Card>
<Microlink url={myurl}/>;
</Card> : null}
</form>
)
}
export default App;

You need to put the onSubmit inside the form tag like this. Also need to have a controlled form. Meaning, you need an onChange, I wrote it for you.
return (
<form onSubmit={event => handleChange(event)} >
<TextField
id="outlined-name"
label="Name"
margin="normal"
variant="outlined"
value={myurl}
onChange={e => setMyUrl(e.target.value)}
/>
<Button
type="submit"
variant="contained"
>
Submit
</Button>
{display ?
<Card>
<Microlink url={myurl}/>;
</Card> : null}
</form>
)
}
export default App;

Related

Why is the function not implemented when I submitted the form?

The function I pass to the onsubmit event is not executed when the form is submitted
import React from 'react';
import styles from './Form.module.css';
import Button from './Button';
const Form = function (props) {
const addUserHandler = function (e) {
e.preventDefault();
console.log(135);
};
return (
<form onSubmit={addUserHandler}>
<input
type='text'
className={styles.input}
placeholder='Your Age'
ref={nameInputRef}
/>
<Button type='submit'>add user</Button>
</form>
);
};
export default Form;
I expected that the function adduserhandler will be executed when I submitted the form.
You are not passing the type correctly from <Button> to <button>, which means that the submit button is rendered as a normal button which does not submit the form. Instead of:
<button type={props.type ? 'button' : props.type}>
do:
<button type={props.type ? props.type : 'button'}>
or shorter:
<button type={props.type || 'button'}>

Formik Fetch API Values Undefined on submit

I am new to react and I need help with submitting my form with values that was obtained from an API.
When the form is loaded, the user has to input an ID in order for it to load the remaining field and values from the API. Once the User has inserted an ID value, the user can then click on submit and the in the back end it should POST the results capture in the Console log. Currently on submit input values are Undefined.
Visit CodeSandbox link below for a working example of this
Code: https://codesandbox.io/s/formik-fetch-post-3remet
Alternatively, here is my Code:
import React, { useState, useEffect } from "react";
import "./styles.css";
import { Box, Button, TextField } from "#mui/material";
import { Formik, Form } from "formik";
export default function App() {
const [datas, setdatas] = useState([]);
const [searchId, setSearchId] = useState("");
useEffect(() => {
fetch(`https://jsonplaceholder.typicode.com/users/?id=${searchId}`)
.then((Response) => Response.json())
.then((datas) => setdatas(datas));
}, [searchId]);
const handleCange = (e) => {
setSearchId(e.target.value);
};
return (
<Formik
initialValues={{ name: datas.name }}
enableReinitialize={true}
onSubmit={(data, { resetForm }) => {
console.log(data);
resetForm();
}}
>
<div className="App">
<h1>Search User(enter a value between 1-5)</h1>
<div className="searchBox">
<input
type="text"
placeholder="Enter user ID"
onChange={(e) => handleCange(e)}
/>
</div>
<div className="itemsSec">
{datas.map((datas) => (
<div key={datas.id} className="items">
<Form>
<Box>
<TextField
className="field"
label="name"
name="name"
type="text"
id="name"
variant="filled"
value={datas.name}
onBlur={Formik.handleBlur}
onChange={Formik.handleChange}
sx={{ gridColumn: "span 2" }}
key={datas.id}
>
{" "}
value={datas.name}
</TextField>
</Box>
<Button type="submit" color="secondary" variant="contained">
Submit
</Button>
</Form>
</div>
))}
</div>
</div>
</Formik>
);
}

Issue in Textfield default value set using the useEffect hook in the material-ui in react

I am trying to set the default value of Textfield in the react material-ui.
It is working without the material-ui Textfield. But when I am using the Textfield it is not working. Ex. Working with "input" but not with "TextField".
I want to use it for form editing purpose. Please help me to find out the solution. Thank you in advance.
Below is the code for the example.
import React,{useEffect,useState } from "react";
import TextField from "#material-ui/core/TextField";
import Button from "#material-ui/core/Button";
const submit = values => {
console.log(values);
};
const initialValues = {
name: '',
};
const Editform = () => {
const [uname, setname] = useState('');
useEffect(() => {
setname("Jubed Alam"); //it should be default value. But not reflecting
});
return (
<form>
<TextField
margin="normal"
label="Name"
fullWidth
name="name"
defaultValue={uname}
/>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</form>
);
}
export default Editform;
i ran into same issue it fixed for me when I used multiline
<TextField
required
id="receiverName"
label="Receiver Name"
defaultValue={addressArray[0]}
fullWidth
multiline
onChange={(e) => setRcvName(e.target.value)}
/>;
you don't need to update its default value in useEffect(). and use value instead of defaultValue, just do it like this:
const Editform = () => {
const [uname, setname] = useState("Jubed Alam");
return (
<form>
<TextField
margin="normal"
label="Name"
fullWidth
name="name"
value={uname}
onChange={(e)=> setname(e.target.value)}
/>
<Button variant="contained" color="primary" type="submit">
Submit
</Button>
</form>
);
}

Cannot edit text inside a React Modal with State to Edit Task Title and Body

I'm wondering if anyone else has had success editing text inside a Bootstrap React Modal and could share some wisdom. I'm using a Bootstrap React Modal to display data once the user clicks on the task title. The data is displaying beautifully, but the user cannot edit the data. The cursor changes to an editing cursor, but no amount of keyboard pounding gets an edit. I tried adding a Bootstrap React Form as you can see below. When I click on the "Save Changes" button, I get my toastify error.
import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Modal from "react-bootstrap/Modal";
import taskAPI from "../../utils/taskAPI";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import "./style.css";
function TaskModal({ onHide, onTaskUpdated, task }) {
const [title, setTitle] = useState("");
const [textBody, setTextBody] = useState("");
const [isPending, setIsPending] = useState(false);
const notify = () => toast.warn("You cannot save an empty task!");
const updateTask=(event)=> {
event.preventDefault();
setIsPending(true);
taskAPI
.updateTask({ title, textBody })
.then((response) => {
response.setTitle("");
response.setTextBody("");
})
.then((response) => {
onTaskUpdated();
setIsPending(false);
})
.catch((error) => {
console.log(error);
setIsPending(false);
notify();
});
}
return (
<>
<Modal show={true} onHide={onHide}>
<Modal.Header closeButton>
<Modal.Title>
<Form>
<Form.Group controlId="TaskTitleText">
<Form.Control
className="TaskTitleText"
as="textarea"
size="lg"
rows="1"
value={task.title}
onChange={(event)=> setTitle(event.target.value)}
/>
</Form.Group>
</Form>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="TaskBodyText">
<Form.Control
as="textarea"
multiple
value={task.textBody}
onChange={(event)=> setTextBody(event.target.value)}
></Form.Control>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
value={isPending ? "Saving..." : "Submit"}
onClick={updateTask}
>
Save Changes
<ToastContainer />
</Button>
<Button variant="secondary"
value={isPending ? "Saving..." : "Submit"}
onClick={onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default TaskModal;
Update your code to below, I have checked it and update the solutions with you.
It will perfectly works everytime.
import React, { useState } from "react";
import Button from "react-bootstrap/Button";
import Form from "react-bootstrap/Form";
import Modal from "react-bootstrap/Modal";
import taskAPI from "../../utils/taskAPI";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import "./style.css";
function TaskModal({ onHide, onTaskUpdated, task }) {
const [title, setTitle] = useState(task.title || "");
const [textBody, setTextBody] = useState(task.textBody || "");
const [isPending, setIsPending] = useState(false);
const notify = () => toast.warn("You cannot save an empty task!");
const updateTask=(event)=> {
event.preventDefault();
setIsPending(true);
taskAPI
.updateTask({ title, textBody })
.then((response) => {
response.setTitle("");
response.setTextBody("");
})
.then((response) => {
onTaskUpdated();
setIsPending(false);
})
.catch((error) => {
console.log(error);
setIsPending(false);
notify();
});
}
return (
<>
<Modal show={true} onHide={onHide}>
<Modal.Header closeButton>
<Modal.Title>
<Form>
<Form.Group controlId="TaskTitleText">
<Form.Control
className="TaskTitleText"
as="textarea"
size="lg"
rows="1"
value={title}
onChange={(event)=> setTitle(event.target.value)}
/>
</Form.Group>
</Form>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="TaskBodyText">
<Form.Control
as="textarea"
multiple
value={textBody}
onChange={(event)=> setTextBody(event.target.value)}
></Form.Control>
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
value={isPending ? "Saving..." : "Submit"}
onClick={updateTask}
>
Save Changes
<ToastContainer />
</Button>
<Button variant="secondary"
value={isPending ? "Saving..." : "Submit"}
onClick={onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</>
);
}
export default TaskModal;
Note that you are setting the value of your Form.Control to task.textBody and not textBody. task.Textbody is a prop that is passed into your element from the parent element, while taskBody is the local state (from useState("")) that you are actually updating in your onChange function.
You probably want to manage the state in a parent component, in which case you can pass down an onChange method that this component can call whenever the text changes.

Material-UI Multiline TextField scrolls horizontally

I'm trying to use Material UI to implement a multiline TextField. Instead of being multi-line the input field is scrolling horizontally. I have replicated the issue in Code Sandbox (link below). It is the Ad Description field in FormItemDetails.js that I want to be multi-line. I'm grateful for any help! Thanks
Code Sandbox
import React, { useState, useEffect } from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
export default function FormItemDetails(props) {
const { values, handleChange } = props;
const [ error, setError ] = useState(null)
console.log(values)
const errorDiv = error
? <div className="error">
<i class="material-icons error-icon">error_outline</i>
{error}
</div>
: '';
useEffect(() => setError(null), []);
function cont(e) {
e.preventDefault();
const requiredFields = ['title', 'description', 'price']
for (const key of requiredFields) {
if (!values[key]) {
setError(`A ${key} is required`)
return
}
}
props.nextStep();
};
function back() {
props.prevStep();
}
return (
<MuiThemeProvider>
<>
<h2>Enter the advertisement details</h2>
{errorDiv}
<TextField
required={true}
fullWidth={true}
hintText="Enter Your Ad Title"
floatingLabelText="Ad Title"
onChange={handleChange('title')}
defaultValue={values.title}
/>
<br />
<TextField
required={true}
fullWidth={true}
multiline
hintText="Enter Your Ad Description"
floatingLabelText="Ad Description"
onChange={handleChange('description')}
defaultValue={values.description}
/>
<br />
<TextField
required
fullWidth
hintText="Enter Your Asking Price"
floatingLabelText="Price"
onChange={handleChange('price')}
defaultValue={values.price}
/>
<br />
<RaisedButton
label="Continue"
primary={true}
style={styles.button}
onClick={cont}
/>
<RaisedButton
label="Back"
primary={false}
style={styles.button}
onClick={back}
/>
</>
</MuiThemeProvider>
)
}
Update the material-ui library used in the project. Actually, you're using material-ui/TextField and have to change to #material-ui/core/TextField for achieved expected behaviour in the textField. Check this demo codesandbox.io/s/t8dkp
Important: Check the last library version as well.

Resources