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

如何根据Autocomplete宽度动态设置limitTags的值?

MUI Autocomplete 实现标签宽度自适应折叠+点击展开全部选中项

要实现标签占满容器宽度时自动折叠为+n,点击时展示全部选中项的效果,需要替换默认的limitTags固定数量逻辑,改用自定义标签渲染和宽度测量的方式。以下是基于你现有代码的修改方案:

核心思路

  • 监听Autocomplete容器宽度,动态计算可容纳的标签数量
  • 自定义renderTags方法,根据宽度判断显示标签或折叠为+n
  • 通过聚焦/失焦事件控制是否展开全部标签

修改后的完整代码

import { useState, useRef } from 'react';
import { Autocomplete, TextField, Chip } from '@mui/material';

const CustomFilterAutocomplete = ({ dropDownOptions, availableWidth = 600 }) => {
  const [value, setValue] = useState([]);
  const [inputValue, setInputValue] = useState('');
  const [isExpanded, setIsExpanded] = useState(false);
  const containerRef = useRef(null);

  return (
    <Autocomplete
      multiple
      freeSolo
      id='multiple-dynamic-limit-tags'
      options={dropDownOptions.map((option) => option.title)}
      value={value}
      inputValue={inputValue}
      onChange={(event, newValue) => {
        setValue([...newValue]);
      }}
      onInputChange={(event, newInputValue) => {
        setInputValue(newInputValue);
      }}
      getOptionLabel={(option) => option}
      ref={containerRef}
      onFocus={() => setIsExpanded(true)}
      onBlur={() => setIsExpanded(false)}
      renderTags={(valueList, getTagProps) => {
        if (!containerRef.current || valueList.length === 0) return null;

        const containerWidth = containerRef.current.offsetWidth;
        const inputElement = containerRef.current.querySelector('input');
        // 预留输入框的最小宽度,可根据实际样式调整
        const inputMinWidth = inputElement ? inputElement.offsetWidth : 120;
        let totalUsedWidth = inputMinWidth;
        const visibleTags = [];

        // 模拟标签样式并计算每个标签的实际宽度
        const getTagWidth = (label) => {
          const tempTag = document.createElement('span');
          // 复制MUI Chip的默认内边距、间距等样式,保证宽度计算准确
          tempTag.style.cssText = `
            display: inline-block;
            margin-right: 8px;
            padding: 6px 12px;
            border-radius: 16px;
            font-size: 0.875rem;
            font-family: Roboto, Helvetica, Arial, sans-serif;
          `;
          tempTag.textContent = label;
          document.body.appendChild(tempTag);
          const width = tempTag.offsetWidth;
          document.body.removeChild(tempTag);
          return width;
        };

        // 遍历标签,计算可容纳的数量
        for (let i = 0; i < valueList.length; i++) {
          const tagWidth = getTagWidth(valueList[i]);
          if (totalUsedWidth + tagWidth > containerWidth) break;
          totalUsedWidth += tagWidth;
          visibleTags.push(valueList[i]);
        }

        // 展开状态下显示全部标签
        if (isExpanded) {
          return valueList.map((option, index) => (
            <Chip
              label={option}
              {...getTagProps({ index })}
              key={index}
              size="small"
            />
          ));
        }

        // 折叠状态下显示可见标签和+n
        const remainingCount = valueList.length - visibleTags.length;
        return [
          ...visibleTags.map((option, index) => (
            <Chip
              label={option}
              {...getTagProps({ index })}
              key={index}
              size="small"
            />
          )),
          remainingCount > 0 && (
            <Chip
              label={`+${remainingCount}`}
              key="remaining"
              size="small"
              disabled
            />
          ),
        ];
      }}
      renderInput={(params) => (
        <TextField {...params} label='Filters' />
      )}
      sx={{ width: availableWidth }}
    />
  );
};

export default CustomFilterAutocomplete;

关键说明

  • 宽度测量:通过临时创建标签元素并计算其宽度,模拟实际渲染后的尺寸,确保判断准确
  • 展开/折叠控制:利用onFocus和onBlur事件切换isExpanded状态,点击输入框时自动展开全部标签
  • 样式一致性:临时标签复制了MUI Chip的默认样式,避免宽度计算偏差
  • freeSolo兼容:保留了原有的自由输入逻辑,不影响自定义标签的添加

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 04:02:52