Can anyone help me replace this Segment with a Modal in ReactJS - reactjs

can anyone help me to replace this Segment with Modal in React JS, here is the code, thanks in advance
return (
<Segment clearing style={{fontWeight: 'bold', fontSize: '20px', backgroundColor: '#f5f7fb'}}> ADD APPOINTMENT
<Form onSubmit={handleSubmit} autoComplete='off'>
<Form.Input placeholder='Customer Name' value={appointment.customerName} name='customerName' onChange={handleInputChange} />
<Form.Input type='date' placeholder='Appointment Date' value={appointment.appointmentDate} name='appointmentDate' onChange={handleInputChange} />
<Form.Input placeholder='Doctor Name' value={appointment.doctorName} name='doctorName' onChange={handleInputChange} />
<Form.Input placeholder='Service' value={appointment.service} name='service' onChange={handleInputChange} />
<Form.Input placeholder='Status' value={appointment.status} name='status' onChange={handleInputChange} />
<Button onClick={submitting} floated='right' positive type='submit' content='Submit' />
<Button onClick={closeForm} floated='right' type='submit' content='Cancel' />
</Form>
</Segment>
)

The below package seems perfect for your needs
https://www.npmjs.com/package/react-modal
below can be your implementation
import React from 'react';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)',
},
};
// Make sure to bind modal to your appElement (https://reactcommunity.org/react-modal/accessibility/)
Modal.setAppElement('#root');
function App() {
let subtitle;
const [modalIsOpen, setIsOpen] = React.useState(false);
function openModal() {
setIsOpen(true);
}
function afterOpenModal() {
// references are now sync'd and can be accessed.
subtitle.style.color = '#f00';
}
function closeModal() {
setIsOpen(false);
}
return (
<div>
<button onClick={openModal}>Open Modal</button>
<Modal
isOpen={modalIsOpen}
onAfterOpen={afterOpenModal}
onRequestClose={closeModal}
style={customStyles}
contentLabel="Example Modal"
>
<Segment clearing style={{fontWeight: 'bold', fontSize: '20px', backgroundColor: '#f5f7fb'}}> ADD APPOINTMENT
<Form onSubmit={handleSubmit} autoComplete='off'>
<Form.Input placeholder='Customer Name' value={appointment.customerName} name='customerName' onChange={handleInputChange} />
<Form.Input type='date' placeholder='Appointment Date' value={appointment.appointmentDate} name='appointmentDate' onChange={handleInputChange} />
<Form.Input placeholder='Doctor Name' value={appointment.doctorName} name='doctorName' onChange={handleInputChange} />
<Form.Input placeholder='Service' value={appointment.service} name='service' onChange={handleInputChange} />
<Form.Input placeholder='Status' value={appointment.status} name='status' onChange={handleInputChange} />
<Button onClick={submitting} floated='right' positive type='submit' content='Submit' />
<Button onClick={closeForm} floated='right' type='submit' content='Cancel' />
</Form>
</Segment>
</Modal>
</div>
);
}
ReactDOM.render(<App />, Document.getElementById("root"));

Related

Targeting 1 Textfield to make its width larger

I have created a form where I am using mui textfields to build the form. I want my textField for the description to be double the width of all the other textFields.
How can I achieve this? To only target one of the textFields
I want to target the last textField in the form and I want that one to be double the width
Below is my code for my form:
import { makeStyles, TextField } from '#material-ui/core';
import { Formik, FormikHelpers } from 'formik';
const useStyles = makeStyles(() => ({
input: {
fontFamily: 'nunito, sans-serif',
color: 'black',
border: '1px solid #393939',
borderRadius: '5px',
marginBottom: '5px',
width: '300px',
padding: '7px',
},
}));
return (
<Formik
initialValues={initialValues}
validationSchema={editUserValidation}
validateOnBlur
validateOnChange={false}
onSubmit={_handleSubmission}
enableReinitialize
>
{({
handleSubmit,
isSubmitting,
values,
touched,
errors,
handleChange,
handleBlur,
handleReset,
}) => (
<form onReset={handleReset} onSubmit={handleSubmit} className="edit-form-body">
<div className="flex">
<TextField
id="firstName"
placeholder="First Name"
type="string"
value={values.firstName}
error={touched.firstName && !!errors.firstName}
helperText={touched.firstName ? errors.firstName : ''}
onChange={handleChange('firstName')}
onBlur={handleBlur('firstName')}
InputProps={{ className: classes.input }}
/>
<div className="mx-5" />
<TextField
id="lastName"
placeholder="Last Name"
type="string"
value={values.lastName}
error={touched.lastName && !!errors.lastName}
helperText={touched.lastName ? errors.lastName : ''}
onChange={handleChange('lastName')}
onBlur={handleBlur('lastName')}
InputProps={{ className: classes.input }}
/>
</div>
<div className="flex">
<TextField
id="email"
placeholder="Email"
type="email"
value={values.email}
error={touched.email && !!errors.email}
helperText={touched.email ? errors.email : ''}
onChange={handleChange('email')}
onBlur={handleBlur('email')}
InputProps={{ className: classes.input }}
/>
<div className="mx-5" />
<TextField
id="mobileNumber"
placeholder="Contact No."
type="string"
value={values.mobileNumber}
error={touched.mobileNumber && !!errors.mobileNumber}
helperText={touched.mobileNumber ? errors.mobileNumber : ''}
onChange={handleChange('mobileNumber')}
onBlur={handleBlur('mobileNumber')}
InputProps={{ className: classes.input }}
/>
</div>
<div className="w-full">
<TextField
id="description"
placeholder="Description"
type="string"
value={values.description}
error={touched.description && !!errors.description}
helperText={touched.description ? errors.description : ''}
onChange={handleChange('description')}
onBlur={handleBlur('description')}
InputProps={{ className: classes.input }}
multiline
maxRows={10}
minRows={5}
/>
</div>
<div className="flex justify-end">
<Button
isLoading={isSubmitting}
onClick={handleSubmit}
className="font-nunito font-bold edit-user-button mt-4"
>
SAVE
</Button>
</div>
</form>
)}
</Formik>
);
};

React Use EmailJS for multiple step Form

I have a React multiple step form, first and second steps is to collect user's image, the third step is user's contact information, and I want to send all this by use EmailJS.
Now I set up emailJS correctly so email does get sent(only last step form), but I don't know how to keep first and second steps' content.
Here is part of my current code:
import "./main.css";
import { Stepper, StepLabel, Step } from "#mui/material";
import Step1 from "../Steps/Step1";
import Step2 from "../Steps/Step2";
import Step3 from "../Steps/Step3";
import { multiStepContext } from "../Steps/StepContext";
import { useContext } from "react";
import { QontoConnector, QontoStepIcon } from "./CustomStepper";
export default function Main(){
const {currentStep, finalData} = useContext(multiStepContext);
function showStep(step){
switch(step){
case 1 :
return <Step1 />
case 2 :
return <Step2 />
case 3 :
return <Step3 />
}
}
return(
<div className="center-steeper">
<Stepper style={{width: "90%", marginTop: "20px", marginBottom: "35px"}}
activeStep={currentStep - 1} orientation="horizontal" alternativeLabel connector={<QontoConnector />}>
<Step>
<StepLabel StepIconComponent={QontoStepIcon}></StepLabel>
</Step>
<Step>
<StepLabel StepIconComponent={QontoStepIcon}></StepLabel>
</Step>
<Step>
<StepLabel StepIconComponent={QontoStepIcon}></StepLabel>
</Step>
</Stepper>
<div>
{showStep(currentStep)}
</div>
</div>
)
}
Step 1:
export default function Step1(){
...
return(
<div className="step-container">
...
<Col span={11} className="upload" style={{ marginRight: "25px" }}>
<div className="upload-photo">
<input id="fusk" type="file" onChange={onChange} style={{display:"none"}} name="origin_pic"/>
...
</div>
</Col>
...
<Row style={{ justifyContent: "space-between"}}>
<Col span={1}></Col>
<Col span={1}>
<button className="btn-next" onClick={() => setStep(2)}>Next</button>
</Col>
</Row>
</div>
)
}
Step 2:
export default function Step2(){
...
return(
<div className="step-container">
...
<input id="fusk" type="file" onChange={onChange} style={{display:"none"}} name="focus_pic"/>
...
<TextArea
className="text-input"
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Write down your concern and what you want to achieve."
autoSize={{
minRows: 7,
maxRows: 10,
}}
name="concern"
/>
<Row style={{ justifyContent: "space-between", alignSelf: "flex-start" }}>
<Col span={1}>
<button className="btn-back" onClick={() => setStep(1)}>Back</button>
</Col>
<Col span={1}>
<button className="btn-next" onClick={() => setStep(3)}>Next</button>
</Col>
</Row>
</div>
)
}
Step 3:
export default function Step3(){
const form = useRef();
const onFinish = (values) => {
console.log('Received values of form: ', values);
};
const { setStep } = useContext(multiStepContext);
const sendEmail = (e) => {
e.preventDefault();
emailjs.sendForm('service_fc2puic', 'template_vpee0kb', form.current, '5EET8rJnlaH9MTLWH')
.then((result) => {
console.log(result.text);
}, (error) => {
console.log(error.text);
});
};
return(
<div className="step-container">
<h2 className="step-title">Step 3: Tell us your contact information</h2>
<form
{...formItemLayout}
ref={form}
name="register"
onFinish={onFinish}
scrollToFirstError
>
...
<Input placeholder="First name" name="first_name"/>
...
<Input placeholder="Last name" name="last_name"/>
...
<Input placeholder="Email" name="email"/>
...
<Input placeholder="Email"/>
...
<Input placeholder="Phone number" name="phone_number"/>
...
<Checkbox defaultChecked={false} disabled value="In-office" name="consultation"><h3 className="option-text">In-office</h3></Checkbox>
<br />
<Checkbox defaultChecked={false} value="Receiving customized video through Email" name="consultation"><h3 className="option-text">Receiving customized video through Email</h3></Checkbox>
<br />
<Checkbox defaultChecked={false} disabled value="Facetime" name="consultation"><h3 className="option-text">Facetime</h3></Checkbox>
<br />
<Checkbox defaultChecked={false} disabled value="Whatsapp" name="consultation"><h3 className="option-text">Whatsapp</h3></Checkbox>
...
</form>
<Row style={{ justifyContent: "space-between", alignSelf: "flex-start" }}>
<Col span={1}>
<button className="btn-back" onClick={() => setStep(2)}>Back</button>
</Col>
<Col span={1}>
<button className="btn-next btn-submit" onClick={sendEmail}>Submit</button>
</Col>
</Row>
</div>
)
}

how to remove blank space for jspdf pdf in react js

I am new to react js and new to creating jspdf pdf. I am creating a pdf for download however I am getting blank space at the top of the pdf like so:
I want to remove this blank space that I am getting in the pdf. My html renders like this:
Here is the function to generate the pdf:
generatePDF = () => {
window.html2canvas = html2canvas;
var doc = new jsPDF("p", "pt", "a4");
doc.html(document.querySelector("#content"), {
callback: function(pdf) {
pdf.save("Coil_Details.pdf");
}
});
};
Here is the function to download data:
getData = async () => {
var ID = this.props.id;
var promise = await this.getAuthorization();
var proxyUrl = "https://cors-anywhere.herokuapp.com/";
console.log("ID:" + ID);
axios({
method: "GET",
url: serverDetails.jwtTokenGenerationURL,
params: {
"jwt-token": jwtService.GetJWT()
}
})
.then(response => {
if (response.statusText != "" && response.statusText != "OK") {
return Promise.reject(response.statusText);
} else {
serverDetails.jwtResponse = response.data;
//return response.data;
}
})
.then(response => {
var url = "api/observation/GetCoilImages";
url += "?jwt=" + serverDetails.jwtResponse;
url += "&ID=" + ID;
axiosAPI
// .get(url)
.get(url)
.then(response => {
if (response.statusText != "" && response.statusText == "OK") {
// window.open(response.data, '_blank');
console.log("Response:" + response.data);
console.log("Response1:" + response.data[0]);
var code = [];
for (var i in response.data) {
code[i] = response.data[i];
console.log("Code:" + code);
}
this.setState({ code });
}
this.setState({
modal: !this.state.modal
});
});
});
};
Here is the html for the same:
return (
<div>
<i
className="fa fa-list-alt"
aria-hidden="true"
// onClick={this.toggle}
onClick={this.getData}
></i>
<Modal
isOpen={this.state.modal}
toggle={this.toggle}
className={this.props.className}
size="lg"
style={{ maxWidth: "700px", width: "100%" }}
>
<ModalHeader
toggle={this.toggle}
cssModule={{ "modal-title": "w-100 text-center" }}
>
Coil Details
</ModalHeader>
<ModalBody>
{/* <Container fluid={true}>
<Card className="card-profile shadow mt--100">
<CardBody> */}
<div id="content">
<div>
<Card className="card-profile shadow">
<center>
{/* <img src={this.props.url} width="100%" height="250px" /> */}
{/* <img src={code} width="100%" height="250px" /> */}
{/* {this.state.code.map(({ src }) => (
<img src={src} key={src} width="40%" height="50px" />
))} */}
{this.state.code.map((imgSrc, index) => (
<img
src={imgSrc}
key={index}
width="100%"
height="250px"
style={{
border: "5px solid #000000",
margin: "3px 3px 3px 3px"
}}
/>
))}
</center>
</Card>
</div>
<hr></hr>
<br></br>
<Row style={{ marginTop: "1rem", marginLeft: "1rem" }}>
<Col lg="3" style={{ marginTop: "1rem" }}>
<FormGroup>
<label>Type</label>
<Input
type="text"
id="typeTextField"
size="sm"
defaultValue={this.props.type}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginTop: "1rem", marginLeft: "3rem" }}>
<FormGroup>
<label>Coil ID</label>
<Input
type="text"
id="coilTextField"
size="sm"
defaultValue={this.props.id}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginTop: "1rem", marginLeft: "3rem" }}>
<FormGroup>
<label>View</label>
<Input
type="text"
id="viewTextField"
size="sm"
defaultValue={this.props.view}
/>
</FormGroup>
</Col>
</Row>
<hr></hr>
<Row style={{ marginLeft: "1rem" }}>
<Col lg="3">
<FormGroup>
<label>Delivery No</label>
<Input
type="text"
id="deliveryTextField"
size="sm"
defaultValue={this.props.delivery}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginLeft: "3rem" }}>
<FormGroup>
<label>Invoice No</label>
<Input
type="text"
id="invoiceTextField"
size="sm"
defaultValue={this.props.invoice}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginLeft: "3rem" }}>
<FormGroup>
<label>Wagon No</label>
<Input
type="text"
id="wagonTextField"
size="sm"
defaultValue={this.props.wagon}
/>
</FormGroup>
</Col>
</Row>
<hr></hr>
<Row style={{ marginLeft: "1rem" }}>
<Col lg="3">
<FormGroup>
<label>Location</label>
<Input
type="text"
id="locationTextField"
size="sm"
defaultValue={this.props.location}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginLeft: "3rem" }}>
<FormGroup>
<label>ICHP</label>
<Input
type="text"
id="ICHPTextField"
size="sm"
defaultValue={this.props.ICHP}
/>
</FormGroup>
</Col>
<Col lg="3" style={{ marginLeft: "3rem" }}>
<FormGroup>
<label>Remarks</label>
<Input
type="textarea"
id="remarksTextField"
size="sm"
defaultValue={this.props.remarks}
/>
</FormGroup>
</Col>
</Row>
<Row>
<Col
lg="5"
style={{ display: "flex", justifyContent: "center" }}
>
<FormGroup>
<label>Date</label>
<Input
type="text"
id="dateTextField"
size="sm"
defaultValue={this.props.date}
/>
</FormGroup>
</Col>
</Row>
</div>
{/* </CardBody>
</Card>
</Container> */}
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.generatePDF}>
Download
</Button>{" "}
<Button color="secondary" onClick={this.toggle}>
Cancel
</Button>
</ModalFooter>
</Modal>
</div>
);
}
}
Why am I getting this blank space at the top and how to remove it. Please help

how to hide one div when another div is active in react js

i have two div login and forget password. i want on forget password login block should be hide and when login block needed forget block should be hidden. Now i able to handle forgot password block , but login block i am not able to handle. I want login block hide on click of forgot button. I have written my own code below. Can some one please suggest me how can i do that.
import React, { useEffect, useState } from 'react';
import useForm from 'react-hook-form';
import { Redirect } from 'react-router-dom';
import './loginForm.css';
const { Header, Content, Footer } = Layout;
const LoginForm = () => {
const [forgotPass, setForgotPass] = useState(false);
if (redirect) {
return <Redirect to={routePaths.DASHBOARD} push />;
}
return (
<Layout>
<Header className="header">
<div>
<img src={logo} className="logo" />
<span className="lft">
<MessageOutlined />
</span>
</div>
</Header>
<Content className="content-screen">
<Row>
<Col xs={24} sm={24} md={8} />
<Col xs={24} sm={24} md={8}>
<div id="loginDiv" className="screen">
<Card title="Login to Relocatte" headStyle={{ backgroundColor: '#69c0ff', border: 1 }}>
<form onSubmit={handleSubmit(onSubmit)}>
{/* <h2 style={{textAlign: 'center'}}>Login</h2> */}
<Row>
<Col style={{ padding: 10 }}>
<Input size="large" placeholder="Enter User Email Here..." onChange={(e) => setValue('email', e.target.value)} />
<ErrorTag errors={errors} name="email" />
</Col>
<Col style={{ padding: 10 }}>
<Input type="password" size="large" placeholder="Enter User Password Here..." onChange={(e) => setValue('encryptedPassword', e.target.value)} />
<ErrorTag errors={errors} name="encryptedPassword" />
</Col>
<Col span={7} style={{ padding: 15 }} className="forget">
Sign Up
</Col>
<Col span={7} style={{ padding: 10 }}>
<Input style={{ cursor: 'pointer' }} type="submit" value="Login" className="login-form-button" shape="round" icon="rollback" />
</Col>
<Col span={10} style={{ padding: 15 }} className="forget">
<a href="#" onClick={() => setForgotPass(!forgotPass)}>Forgot Password</a>
{/* <button onClick={() => setForgotPass(!forgotPass)}>Forgot Password</button> */}
</Col>
</Row>
</form>
</Card>
</div>
</Col>
<Col xs={24} sm={24} md={8}>
{/* forgot div goes here */}
{forgotPass
&& (
<div className="screen">
<Card title="Forgot Password" headStyle={{ backgroundColor: '#69c0ff', border: 1 }}>
<form onSubmit={handleSubmit(onSubmit)}>
{/* <h2 style={{textAlign: 'center'}}>Login</h2> */}
<Row>
<Col style={{ padding: 10 }}>
<Input size="large" placeholder="Enter Registered Email Here..." onChange={(e) => setValue('', e.target.value)} />
<ErrorTag errors={errors} name="" />
</Col>
<Col span={12} style={{ padding: 10 }}>
<Input style={{ cursor: 'pointer' }} type="submit" value="Send Reset Link" className="login-form-button" shape="round" icon="rollback" />
</Col>
<Col span={10} style={{ padding: 15 , textAlign: "right"}} className="forget">
<a href="#" onClick={() => setForgotPass(!forgotPass)}>Login</a>
{/* <button onClick={() => setForgotPass(!forgotPass)}>Forgot Password</button> */}
</Col>
</Row>
</form>
</Card>
</div>
)}
</Col>
</Row>
</Content>
<Footer className="footer-back">
<Row>
<Col xs={24} sm={24} md={12} className="foot-child-1">
All Right Reserved© 2020 Relocatte
</Col>
<Col xs={24} sm={24} md={12} className="foot-child-2">
<span>Privacy Policy</span>
<span> | </span>
<span>Term & Conditions</span>
</Col>
</Row>
</Footer>
</Layout>
);
};
export default LoginForm;
Hi Please check this example:
import React, {useEffect, useState} from 'react';
const LoginForm = () => {
const [forgotPass, setForgotPass] = useState(false);
function handleLogin(event) {
}
function handleForgot(event) {
setForgotPass(!forgotPass);
}
function handleReset(event) {
alert('Your password is reset');
setForgotPass(!forgotPass);
}
return (
<div>
{forgotPass ?
(<div>
Username: <input/> <br/>
<button onClick={handleReset}>Reset Password</button>
</div>)
:
(<div>
Username: <input/> <br/>
Password: <input/> <br/>
<button onClick={handleLogin}>Login</button>
<button onClick={handleForgot}>Forgot Password</button>
</div>)
}
</div>
);
};
export default LoginForm;
There are 2 ways of doing it
Using ternary operator
return (<div className="container">
{forgotPass ? <div>Forget password div </div> : <div> Login Div</div>}
</div>)
Using CSS
return (<div className="container">
<div className={forgotPass ? "show" : "hide"}>Forget password div </div>
<div className={!forgotPass ? "show" : "hide"}> Login Div</div>}
</div>)
in your css:
.show { display: 'block' }
.hide { display: 'none' }

How to enable file upload on React's Material UI simple input?

I am creating a simple form to upload file using electron-react-boilerplate with redux form & material ui.
The problem is that I do not know how to create input file field because material ui does not support upload file input.
Any ideas on how to achieve this?
The API provides component for this purpose.
<Button
variant="contained"
component="label"
>
Upload File
<input
type="file"
hidden
/>
</Button>
newer MUI version:
<input
accept="image/*"
className={classes.input}
style={{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
/>
<label htmlFor="raised-button-file">
<Button variant="raised" component="span" className={classes.button}>
Upload
</Button>
</label>
You need to wrap your input with component, and add containerElement property with value 'label' ...
<RaisedButton
containerElement='label' // <-- Just add me!
label='My Label'>
<input type="file" />
</RaisedButton>
You can read more about it in this GitHub issue.
EDIT: Update 2019.
Check at the bottom answer from #galki
TLDR;
<input
accept="image/*"
className={classes.input}
style={{ display: 'none' }}
id="raised-button-file"
multiple
type="file"
/>
<label htmlFor="raised-button-file">
<Button variant="raised" component="span" className={classes.button}>
Upload
</Button>
</label>
Here's an example using an IconButton to capture input (photo/video capture) using v3.9.2:
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import IconButton from '#material-ui/core/IconButton';
import PhotoCamera from '#material-ui/icons/PhotoCamera';
import Videocam from '#material-ui/icons/Videocam';
const styles = (theme) => ({
input: {
display: 'none'
}
});
class MediaCapture extends Component {
static propTypes = {
classes: PropTypes.object.isRequired
};
state: {
images: [],
videos: []
};
handleCapture = ({ target }) => {
const fileReader = new FileReader();
const name = target.accept.includes('image') ? 'images' : 'videos';
fileReader.readAsDataURL(target.files[0]);
fileReader.onload = (e) => {
this.setState((prevState) => ({
[name]: [...prevState[name], e.target.result]
}));
};
};
render() {
const { classes } = this.props;
return (
<Fragment>
<input
accept="image/*"
className={classes.input}
id="icon-button-photo"
onChange={this.handleCapture}
type="file"
/>
<label htmlFor="icon-button-photo">
<IconButton color="primary" component="span">
<PhotoCamera />
</IconButton>
</label>
<input
accept="video/*"
capture="camcorder"
className={classes.input}
id="icon-button-video"
onChange={this.handleCapture}
type="file"
/>
<label htmlFor="icon-button-video">
<IconButton color="primary" component="span">
<Videocam />
</IconButton>
</label>
</Fragment>
);
}
}
export default withStyles(styles, { withTheme: true })(MediaCapture);
It is work for me ("#material-ui/core": "^4.3.1"):
<Fragment>
<input
color="primary"
accept="image/*"
type="file"
onChange={onChange}
id="icon-button-file"
style={{ display: 'none', }}
/>
<label htmlFor="icon-button-file">
<Button
variant="contained"
component="span"
className={classes.button}
size="large"
color="primary"
>
<ImageIcon className={classes.extendedIcon} />
</Button>
</label>
</Fragment>
If you're using React function components, and you don't like to work with labels or IDs, you can also use a reference.
const uploadInputRef = useRef(null);
return (
<Fragment>
<input
ref={uploadInputRef}
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={onChange}
/>
<Button
onClick={() => uploadInputRef.current && uploadInputRef.current.click()}
variant="contained"
>
Upload
</Button>
</Fragment>
);
Official recommendation
import * as React from 'react';
import { styled } from '#mui/material/styles';
import Button from '#mui/material/Button';
import IconButton from '#mui/material/IconButton';
import PhotoCamera from '#mui/icons-material/PhotoCamera';
import Stack from '#mui/material/Stack';
const Input = styled('input')({
display: 'none',
});
export default function UploadButtons() {
return (
<Stack direction="row" alignItems="center" spacing={2}>
<label htmlFor="contained-button-file">
<Input accept="image/*" id="contained-button-file" multiple type="file" />
<Button variant="contained" component="span">
Upload
</Button>
</label>
<label htmlFor="icon-button-file">
<Input accept="image/*" id="icon-button-file" type="file" />
<IconButton color="primary" aria-label="upload picture" component="span">
<PhotoCamera />
</IconButton>
</label>
</Stack>
);
}
Nov 2020
With Material-UI and React Hooks
import * as React from "react";
import {
Button,
IconButton,
Tooltip,
makeStyles,
Theme,
} from "#material-ui/core";
import { PhotoCamera } from "#material-ui/icons";
const useStyles = makeStyles((theme: Theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
},
},
input: {
display: "none",
},
faceImage: {
color: theme.palette.primary.light,
},
}));
interface FormProps {
saveFace: any; //(fileName:Blob) => Promise<void>, // callback taking a string and then dispatching a store actions
}
export const FaceForm: React.FunctionComponent<FormProps> = ({ saveFace }) => {
const classes = useStyles();
const [selectedFile, setSelectedFile] = React.useState(null);
const handleCapture = ({ target }: any) => {
setSelectedFile(target.files[0]);
};
const handleSubmit = () => {
saveFace(selectedFile);
};
return (
<>
<input
accept="image/jpeg"
className={classes.input}
id="faceImage"
type="file"
onChange={handleCapture}
/>
<Tooltip title="Select Image">
<label htmlFor="faceImage">
<IconButton
className={classes.faceImage}
color="primary"
aria-label="upload picture"
component="span"
>
<PhotoCamera fontSize="large" />
</IconButton>
</label>
</Tooltip>
<label>{selectedFile ? selectedFile.name : "Select Image"}</label>. . .
<Button onClick={() => handleSubmit()} color="primary">
Save
</Button>
</>
);
};
You can use Material UI's Input and InputLabel components. Here's an example if you were using them to input spreadsheet files.
import { Input, InputLabel } from "#material-ui/core";
const styles = {
hidden: {
display: "none",
},
importLabel: {
color: "black",
},
};
<InputLabel htmlFor="import-button" style={styles.importLabel}>
<Input
id="import-button"
inputProps={{
accept:
".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel",
}}
onChange={onInputChange}
style={styles.hidden}
type="file"
/>
Import Spreadsheet
</InputLabel>
import AddPhotoIcon from "#mui/icons-material/AddAPhoto";
import Fab from "#mui/material/Fab";
<Fab color="primary" aria-label="add-image" sx={{ position: "fixed", bottom: 16, right: 16, overflow: "hidden" }}>
<input
type="file"
onChange={imageHandler}
accept=".jpg, .jpeg, .png"
accept="image/*"
multiple
style={{ //make this hidden and display only the icon
position: "absolute",
top: "-35px",
left: 0,
height: "calc(100% + 36px)",
width: "calc(100% + 5px)",
outline: "none",
}}
/>
<AddPhotoIcon />
</Fab>
Just the same as what should be but change the button component to be label like so
<form id='uploadForm'
action='http://localhost:8000/upload'
method='post'
encType="multipart/form-data">
<input type="file" id="sampleFile" style="display: none;" />
<Button htmlFor="sampleFile" component="label" type={'submit'}>Upload</Button>
</form>
<input type="file"
id="fileUploadButton"
style={{ display: 'none' }}
onChange={onFileChange}
/>
<label htmlFor={'fileUploadButton'}>
<Button
color="secondary"
className={classes.btnUpload}
variant="contained"
component="span"
startIcon={
<SvgIcon fontSize="small">
<UploadIcon />
</SvgIcon>
}
>
Upload
</Button>
</label>
Make sure Button has component="span", that helped me.
Here an example:
return (
<Box alignItems='center' display='flex' justifyContent='center' flexDirection='column'>
<Box>
<input accept="image/*" id="upload-company-logo" type='file' hidden />
<label htmlFor="upload-company-logo">
<Button component="span" >
<Paper elevation={5}>
<Avatar src={formik.values.logo} className={classes.avatar} variant='rounded' />
</Paper>
</Button>
</label>
</Box>
</Box>
)
Typescript version of #tomatentobi's javascript solution
const uploadInputRef = useRef<HTMLInputElement | null>(null);
return (
<>
<input
ref={uploadInputRef}
type="file"
accept="image/*"
style={{ display: "none" }}
onChange={onChange}
/>
<Button
onClick={() => uploadInputRef.current && uploadInputRef.current.click()}
variant="contained">
Upload
</Button>
</>
);
This worked for me.
<Button variant="contained" component="label" >
UPLOAD
<input accept="image/*" hidden type="file" />
</Button>
You can pursue all the comments above, those are really great, However, I have another option for customizing your component, if you want to follow.
// Import
import { styled } from '#mui/material/styles';
import { Input } from "#mui/material";
// Custom style
const CustomFileInput = styled(Input)(({ theme }) => {
return {
color: "white",
'::before': {
border: 'none',
position: 'static',
content: 'none'
},
'::after': {
border: 'none',
position: 'static',
content: 'none'
}
}
});
// Using that component
<CustomFileInput type="file" />
Both #galki and #elijahcarrel method works fine.
If anyone trying to do unit-testing(jest) for these two answers.
You wont be able to use the button component with (specially if you are using disabled=true
expect(getByRole("button", {name: "Upload"})).not.toBeEnabled();
instead use this
expect(getByLabelText("Upload")).not.toBeEnabled();
This is for Select Image File
<IconButton color="primary" component="label">
<input type="file" accept="image/*" hidden />
<AttachFileIcon fontSize="medium" />
</IconButton>
NOTE : React Material UI Component (IconButton, AttachFileIcon)
Or there is library for MUI 5 / React 18 : https://viclafouch.github.io/mui-file-input/ 🔥
import React from 'react'
import { MuiFileInput } from 'mui-file-input'
const MyComponent = () => {
const [value, setValue] = React.useState(null)
const handleChange = (newValue) => {
setValue(newValue)
}
return <MuiFileInput value={value} onChange={handleChange} />
}
Try This
import React from 'react'
import { MuiFileInput } from 'mui-file-input'
export default function MyComponent () {
const [file, setFile] = React.useState(null)
const handleChange = (newFile) => {
setFile(newFile)
}
return (
<MuiFileInput value={file} onChange={handleChange} />
)
}
npm install mui-file-input --save
npm install #mui/icons-material
or
yarn add mui-file-input
yarn add #mui/icons-material
another way is this and we can add the name of the file as a value for TextField.
<TextField
value={state.value}
label="upload profile picture"
sx={{ m: 1, width: '25ch' }}
InputProps={{
fullWidth: true,
startAdornment: (
<IconButton component="label">
<AttachFileIcon />
<input
type="file"
hidden
onChange={handleUploadInput}
name="[name]"
/>
</IconButton>
)
}}
/>

Resources