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

Material UI DataGrid自定义复选框:加载时显示状态并保留选中功能

解决Material UI DataGrid加载时替换复选框为加载状态并保留选中功能的方案

方法一:自定义选择列+复用DataGrid原生选中逻辑

关闭DataGrid默认的复选框选择,自定义一列来实现“加载时显示加载组件,完成后显示复选框”的效果,同时通过apiRef调用DataGrid内置的选中方法,完全保留原生选择功能。

import { DataGrid, CircularProgress } from '@mui/x-data-grid';
import { useGridApiRef } from '@mui/x-data-grid';
import { useState, useEffect } from 'react';

export default function LoadingAwareDataGrid() {
  const apiRef = useGridApiRef();
  const [loading, setLoading] = useState(true);
  const [rows, setRows] = useState([]);

  // 模拟异步数据加载
  useEffect(() => {
    setTimeout(() => {
      setRows([
        { id: 1, name: 'John Doe', age: 35 },
        { id: 2, name: 'Jane Smith', age: 28 },
        { id: 3, name: 'Bob Brown', age: 42 },
      ]);
      setLoading(false);
    }, 2000);
  }, []);

  // 自定义选择列配置
  const selectionColumn = {
    field: 'selection',
    headerName: '',
    width: 50,
    renderCell: (params) => {
      if (loading) {
        return <CircularProgress size={20} />;
      }
      // 复用原生选中逻辑
      return (
        <input
          type="checkbox"
          checked={apiRef.current.isRowSelected(params.id)}
          onChange={() => apiRef.current.toggleRowSelection(params.id)}
        />
      );
    },
    renderHeader: () => {
      if (loading) {
        return <CircularProgress size={20} />;
      }
      // 表头复选框同样处理
      return (
        <input
          type="checkbox"
          checked={apiRef.current.isAllRowsSelected()}
          onChange={() => apiRef.current.toggleAllRowsSelection()}
        />
      );
    },
  };

  const columns = [
    selectionColumn,
    { field: 'name', headerName: 'Name', width: 150 },
    { field: 'age', headerName: 'Age', width: 100 },
  ];

  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid
        apiRef={apiRef}
        rows={rows}
        columns={columns}
        checkboxSelection={false} // 关闭默认复选框
        onRowSelectionModelChange={(selectedIds) => {
          console.log('选中行ID列表:', selectedIds);
          // 这里可以直接拿到选中行的ID,做后续处理
        }}
      />
    </div>
  );
}

方法二:自定义BaseCheckbox组件并保留原生props

如果要沿用DataGrid默认的复选框列,直接替换BaseCheckbox组件即可,核心是传递所有原生props,确保原有选中逻辑不丢失,同时通过onRowSelectionModelChange直接获取选中行数据。

import { DataGrid, BaseCheckbox } from '@mui/x-data-grid';
import { CircularProgress } from '@mui/material';
import { useState, useEffect } from 'react';

export default function CustomCheckboxGrid() {
  const [loading, setLoading] = useState(true);
  const [rows, setRows] = useState([]);

  useEffect(() => {
    setTimeout(() => {
      setRows([
        { id: 1, name: 'Alice', age: 30 },
        { id: 2, name: 'Bob', age: 40 },
        { id: 3, name: 'Charlie', age: 25 },
      ]);
      setLoading(false);
    }, 2000);
  }, []);

  const columns = [
    { field: 'name', headerName: 'Name', width: 150 },
    { field: 'age', headerName: 'Age', width: 100 },
  ];

  return (
    <div style={{ height: 400, width: '100%' }}>
      <DataGrid
        rows={rows}
        columns={columns}
        checkboxSelection
        components={{
          BaseCheckbox: (props) => {
            if (loading) {
              return <CircularProgress size={20} />;
            }
            // 必须传递所有props,保留原生选中逻辑
            return <BaseCheckbox {...props} />;
          },
        }}
        onRowSelectionModelChange={(selectedIds) => {
          console.log('选中行ID:', selectedIds);
          // 如需获取完整行数据,可通过apiRef或直接从rows数组筛选
          const selectedRows = rows.filter(row => selectedIds.includes(row.id));
          console.log('选中行详情:', selectedRows);
        }}
      />
    </div>
  );
}

关键注意点

  • 自定义组件时必须传递所有原生props,尤其是checked和onChange,否则会丢失选中状态同步逻辑
  • 不要手动重写onClick事件,直接使用DataGrid提供的onRowSelectionModelChange回调,能直接拿到选中行ID数组,无需自行解析点击事件
  • 表头复选框的状态切换逻辑,通过apiRef调用内置方法即可,无需手动实现全选/反选逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 15:45:26