如何将上传图标修复为文件上传输入(材料 UI)

Posted

技术标签:

【中文标题】如何将上传图标修复为文件上传输入(材料 UI)【英文标题】:How to fix an upload icon to a file upload input (material UI) 【发布时间】:2021-10-24 05:47:49 【问题描述】:

我目前正在尝试使用 Material UI 构建一个带有图标作为输入装饰的文件上传输入字段。我希望能够点击图标上传文件。

按照此处的 MUI 文档:input adornment,我尝试遵循确切的格式,除了在演示中使用 IconButton 而不是密码可见性图标。

这是我的代码示例:

   <FormControl className=classes.formControl>
      <InputLabel htmlFor="upload-script">Sim Script</InputLabel>
      <Input
        id="upload-script"
        type="file"
        value=values.script
        onChange=() => handleChange('script')
        endAdornment=
          <InputAdornment position="end">
            <IconButton aria-label="upload">
              <PublishIcon />                        // (here is my icon)
            </IconButton>
          </InputAdornment>
        
      />
    </FormControl>

这可行,但结果完全不是我想要的 - 这是它在浏览器中的截图:

您可以在右侧一直看到我的上传图标,但输入字段显然有自己的上传按钮和占位符文本('未选择文件')。

看网上,看到这里有一个建议:(similar *** post) 说我们应该在Input 组件中添加style: display: none ,并添加component="span" 作为IconButton 的属性。然而,当我尝试这个时,浏览器给我们的是这样的:

(一直滚动...我的源图标不见了,输入字段下方没有行分隔符,间距明显混乱...)

显然,这些都不是我想要的哈哈。有人可以帮忙吗?? (我希望这个描述足够好......)

非常感谢!!

-

编辑: 这是@Shiladitya 的初始解决方案的样子:

但我希望文本字段有一行!我希望它看起来与“Sim Binary”文本字段完全一样,只是右侧有一个上传图标而不是下拉箭头。

【问题讨论】:

【参考方案1】:

给你一个解决方案

const handleFileUpload = () =&gt; 
<>
  <input
    style=
      display: "none"
    
    accept=".json"  // specify the file type that you wanted to accept
    id="choose-file"
    type="file"
    onChange=handleFileUpload
  />
  <label htmlFor="choose-file">
    <IconButton aria-label="upload">
      <PublishIcon />
    </IconButton>
  </label>
</>

使用文本字段编辑

     <TextField
        className=classes.margin
        id="input-with-icon-textfield"
        label="TextField"
        InputProps=
          endAdornment: (
            <>
              <input
                style=
                  display: "none"
                
                accept=".json"
                id="choose-file"
                type="file"
                onChange=handleFileUpload
              />
              <label htmlFor="choose-file">
                <IconButton aria-label="upload">
                  <PublishIcon />
                </IconButton>
              </label>
            </>
          ),
        
      />

【讨论】:

但这只是隐藏了输入标签字段,所以你看到的只是图标。我希望图标显示在文本字段的末尾,以便用户最终可以看到选择上传的文件。 @tprebenda 请找到更新后的答案 这个更新的答案是完美的,谢谢!!【参考方案2】:

另一种解决方案。

* 
  margin: 0 auto;
  font-family: Helvetica;

html 
  background-color: #e9e9e9;


#choose-file 
  display: none;


#wrapper 
  display: inline-flex;
  justify-content: center;
  margin-left: 20px;
  background-color: orange;
  width: 60px;
  align-items: center;
  cursor: pointer;
<form>
  <label id="first">
   Sim Binary
  <div id="wrapper">
  <input
    accept=".json"
    id="choose-file"
    type="file"
  />
     ⇪
  </div>
     </label>
</form>

【讨论】:

【参考方案3】:

我最近返回并编辑了我的组件,该组件的灵感来自@Shiladitya,但现在使用了一个我以前不知何故错过的更好的系统:

<TextField
  className=classes.formControl
  id=`sim-script-$sim.uuid`
  label="Sim Script- click the Upload Icon"
  required
  inputRef=scriptInputRef     // To focus on the field after clicking icon
  value=sim.script
  InputProps=
    readOnly: true,
    endAdornment: (
      <>
        <AdjustedTooltip title="Upload script" arrow>
          <IconButton
            aria-label="upload"
            className=classes.uploadIcon
            component="label"             // THIS IS THE GENIUS CHANGE
          >
            <PublishIcon />
            <input
              hidden
              type="file"
              onChange=(e) => scriptUpload(e)
            />
          </IconButton>
        </AdjustedTooltip>
      </>
    ),
  
/>

这样,我们可以移除所有的输入和标签包装,而只需将 Material UI Button 设置为具有component="label" 属性,并将输入标签放在图标按钮内。

这也是我的 onChange/scriptUpload 函数,以防人们感兴趣:

const scriptUpload = (e: ChangeEvent<HTMLInputElement>) => 
  // the first/only file selected by user
  if (e.target.files?.item(0))   
    onChange(sim.uuid, "script", e.target.files?.item(0)!.name);
  

  // Focus textfield
  if (scriptInputRef.current) 
    scriptInputRef.current.focus();
  
;

【讨论】:

以上是关于如何将上传图标修复为文件上传输入(材料 UI)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 REST API 将文件和附件上传到 sobject 记录?

gitlab上可以上传文本材料吗

上海微法院pdf格式上传了

如何将本地的项目上传到github上?

如何修复 React/Redux/Firebase 错误上传文件到存储

JavaScript中上传文件为图片如何读取(UI组件之图片剪裁器)