Skip to content

Instantly share code, notes, and snippets.

@maruware
Created September 4, 2019 07:40
Show Gist options
  • Save maruware/090282eda60ac80793e779101ccc48c2 to your computer and use it in GitHub Desktop.
Save maruware/090282eda60ac80793e779101ccc48c2 to your computer and use it in GitHub Desktop.
Material UI - Image File Input
import React, { useState, useEffect } from 'react'
import PhotoLibraryIcon from '@material-ui/icons/PhotoLibrary'
import Button from '@material-ui/core/Button'
import { makeStyles } from '@material-ui/core/styles'
import PlaceholderImage from './PlaceholderImage'
const useStyles = makeStyles(theme => ({
textContainer: {
paddingTop: 0
},
text: {
fontSize: 16
},
image: {
width: 160,
height: 120,
objectFit: 'contain'
},
buttonIcon: {
marginRight: theme.spacing(1)
},
imageContainer: {
marginBottom: theme.spacing(1)
}
}))
interface ImageFileInputProps {
className?: string
value: File | null
onChange: (file: File | null) => void
}
const ImageFileInput: React.FC<ImageFileInputProps> = ({
className,
value,
onChange,
children
}) => {
const classes = useStyles()
const [dataUrl, setDataUrl] = useState<string | null>(null)
useEffect(() => {
if (value) {
const reader = new FileReader()
reader.onload = () => {
const dataUrl = reader.result as string
setDataUrl(dataUrl)
}
reader.readAsDataURL(value)
} else {
setDataUrl(null)
}
}, [value])
const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!e.target.files) {
onChange(null)
return
}
const file = e.target.files[0]
if (!file || !file.type.match('image.*')) {
onChange(null)
return
}
onChange(file)
}
return (
<div className={className}>
<div className={classes.imageContainer}>
{dataUrl && <img src={dataUrl} className={classes.image} />}
{!dataUrl && <PlaceholderImage width={200} height={150} />}
</div>
<Button variant="contained" color="primary" component="label">
<PhotoLibraryIcon className={classes.buttonIcon} />
{children}
<input
onChange={handleFileSelect}
style={{ display: 'none' }}
type="file"
accept="image/*"
/>
</Button>
</div>
)
}
export default ImageFileInput
import React from 'react'
import { makeStyles } from '@material-ui/core/styles'
import ImageIcon from '@material-ui/icons/Image'
interface PlaceHolderImageProps {
width: number
height: number
}
const useStyles = makeStyles(theme => ({
root: {
backgroundColor: theme.palette.grey[300],
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}))
const PlaceholderImage: React.FC<PlaceHolderImageProps> = ({
width,
height
}) => {
const classes = useStyles()
return (
<div style={{ width, height }} className={classes.root}>
<ImageIcon fontSize="large" />
</div>
)
}
export default PlaceholderImage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment