如何将上传图标修复到文件上传输入 (material UI)

How to fix an upload icon to a file upload input (material UI)

我目前正在尝试使用 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>

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

你可以在右边一直看到我的上传图标,但是输入框显然有自己的上传按钮和占位符文本('No file chosen')。

在网上看,我在这里看到一个建议: 说我们应该将 style: {{ display: none }} 添加到 Input 组件,并将 component="span" 添加为 属性 图标按钮。然而,当我尝试这个时,浏览器给我们的是:

(这是一直滚动...我的来源图标不见了,输入字段下面没有行分隔符,间距显然乱七八糟...)

很明显,这两个都不是我想要的哈哈。谁能帮忙?? (我希望这个描述足够好......)

非常感谢!!

-

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

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

给你一个解决方案

const handleFileUpload = () => {}
<>
  <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>
            </>
          ),
        }}
      />

另一个解决方案。

* {
  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>

我最近返回并编辑了我的组件,它的灵感来自@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 按钮设置为具有 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();
  }
};