You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SolidJS中Material UI风格Autocomplete组件实现及相关API疑问

SolidJS 中类似 Material UI Autocomplete 的替代方案与自定义实现

替代库推荐

因为SUID暂未提供Autocomplete组件,你可以考虑以下几种方案:

  • Solid-Autocomplete:SolidJS生态中专门的轻量组件,支持自由输入、选项过滤,样式可自定义,能无缝配合SUID的TextField使用
  • PrimeReact Autocomplete(Solid版):PrimeReact的SolidJS适配组件,自带Material风格样式,开箱即支持编辑+下拉选择功能
  • 自定义封装:基于SUID现有组件(TextField + Menu + Popup)手动实现,灵活性最高,完全适配SUID的设计体系

TextField select 属性与 Select input 元素的作用

先明确这两个属性的核心功能:

  • TextField的select属性:当设置为true时,TextField会渲染原生<select>元素,而非普通文本输入框。此时需要搭配MenuItem作为子元素提供选项,但原生<select>不支持自由编辑输入——这就是你之前只得到普通选择框的原因。
  • Select的input属性:用于替换Select组件内部默认的输入元素,但Select本身是纯下拉选择组件,默认不允许自由输入,仅支持选择预定义选项。

实现可编辑+下拉选择的自定义组件(基于SUID)

如果要兼顾自由编辑和预定义选项选择,推荐用SUID的基础组件手动封装,示例代码如下:

import { createSignal, Show } from "solid-js";
import { TextField, Menu, MenuItem, IconButton, Popup } from "@suid/material";
import { ExpandMore } from "@suid/icons-material";

// 可编辑下拉选择组件
const EditableSelect = ({ options, placeholder }: { options: string[], placeholder?: string }) => {
  const [inputValue, setInputValue] = createSignal("");
  const [isMenuOpen, setIsMenuOpen] = createSignal(false);
  const [filteredOptions, setFilteredOptions] = createSignal(options);

  // 输入时实时过滤选项
  const handleInputChange = (e: Event) => {
    const value = (e.target as HTMLInputElement).value;
    setInputValue(value);
    setFilteredOptions(
      options.filter(opt => opt.toLowerCase().includes(value.toLowerCase()))
    );
  };

  // 选择选项后填充输入框并关闭菜单
  const handleOptionSelect = (option: string) => {
    setInputValue(option);
    setIsMenuOpen(false);
  };

  return (
    <div style={{ position: "relative", width: 320 }}>
      <TextField
        value={inputValue()}
        onChange={handleInputChange}
        placeholder={placeholder}
        fullWidth
        endAdornment={
          <IconButton onClick={() => setIsMenuOpen(!isMenuOpen())}>
            <ExpandMore />
          </IconButton>
        }
      />
      {/* 下拉菜单 */}
      <Popup 
        open={isMenuOpen()} 
        onOpenChange={setIsMenuOpen}
        anchorEl={document.querySelector(".MuiTextField-root")}
      >
        <Menu>
          <Show when={filteredOptions().length > 0}>
            {filteredOptions().map(opt => (
              <MenuItem onClick={() => handleOptionSelect(opt)}>
                {opt}
              </MenuItem>
            ))}
          </Show>
          <Show when={filteredOptions().length === 0 && inputValue() !== ""}>
            <MenuItem disabled>无匹配选项</MenuItem>
          </Show>
        </Menu>
      </Popup>
    </div>
  );
};

// 使用示例
const App = () => {
  const fruitOptions = ["苹果", "香蕉", "樱桃", "榴莲"];
  return (
    <div style={{ padding: "2rem" }}>
      <EditableSelect 
        options={fruitOptions} 
        placeholder="输入或选择水果" 
      />
    </div>
  );
};

export default App;

示例说明

  • 用TextField作为基础输入框,支持用户自由编辑输入内容
  • 通过Popup和Menu实现下拉选项面板,点击右侧图标切换面板显示状态
  • 输入内容时自动过滤匹配的选项,提升用户体验
  • 选择选项后自动填充到输入框,并关闭下拉面板

常见问题说明

如果你之前尝试设置TextField select={true}却没得到选择功能,大概率是因为没有搭配MenuItem子元素,正确的原生select用法示例如下(仅支持选择,不支持编辑):

import { createSignal } from "solid-js";
import { TextField, MenuItem } from "@suid/material";

const BasicSelect = () => {
  const [value, setValue] = createSignal("apple");
  return (
    <TextField
      select
      value={value()}
      onChange={(e) => setValue(e.target.value)}
      placeholder="选择水果"
      fullWidth
    >
      <MenuItem value="apple">苹果</MenuItem>
      <MenuItem value="banana">香蕉</MenuItem>
    </TextField>
  );
};

内容的提问来源于stack exchange,提问作者vjalle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 11:33:17