我正在创建一个简单的形式上传文件使用电子反应样板与还原形式和材料 UI。
问题是,我不知道如何创建输入文件字段,因为材料 ui 不支持上传文件输入。
对于如何实现这一点有什么想法吗?
您需要用 组件包装您的输入,并用 价值’标签’添加 集装箱元素属性..。
<RaisedButton containerElement='label' // <-- Just add me! label='My Label'> <input type="file" /> </RaisedButton>
您可以在这个 GitHub 问题中了解更多信息。
编辑: 更新2019。
检查从 @ galki的底部答案
极低密度辐射;
<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>
更新的 MUI 版本:
API 为此提供了 component。
component
<Button variant="contained" component="label" > Upload File <input type="file" hidden /> </Button>
下面是一个使用 IconButton 使用 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);
这是我的工作(“@Materials-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>
就像应该是什么一样,但是改变按钮组件为标签,如下所示
<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>
如果您正在使用 React 函数组件,并且不喜欢使用标签或 ID,那么还可以使用引用。
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> );
<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>
确保 Button 具有 Component = “ span” ,这对我有帮助。
可以使用 Materials UI 的 Input 和 InputLabel 组件。这里有一个例子,如果您使用它们来输入电子表格文件。
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 * 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> </> ); };
举个例子:
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> )
你可以继续上面的所有评论,那些真的很棒,但是,我有另一个选项来定制您的组件,如果你想遵循。
//进口
import { styled } from '@mui/material/styles'; import { Input } from "@mui/material";
//自订风格
const CustomFileInput = styled(Input)(({ theme }) => { return { color: "white", '::before': { border: 'none', position: 'static', content: 'none' }, '::after': { border: 'none', position: 'static', content: 'none' } } });
//使用该组件
<CustomFileInput type="file" />
@ galki 和@elijahcarrel 方法都很好用。 如果有人试图对这两个答案进行单元测试(开玩笑)。
您不能使用带有 < code > 的按钮组件(特别是如果您正在使用 禁用 = true
expect(getByRole("button", {name: "Upload"})).not.toBeEnabled();
而不是用这个
expect(getByLabelText("Upload")).not.toBeEnabled();
官方推荐
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> ); }
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>
这是用于选择图像文件
<IconButton color="primary" component="label"> <input type="file" accept="image/*" hidden /> <AttachFileIcon fontSize="medium" /> </IconButton>
注意: < em > React Materials UI Component (IconButton,AttachFileIcon)
另一种方法是这样,我们可以添加文件名作为 TextField的值。
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> ) }} />
@ tomatentobi 的 javascript 解决方案的打字稿版本
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> </> );
或者有一个 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} /> }
试试这个
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
或者
yarn add mui-file-input yarn add @mui/icons-material