【问题标题】:How can I specify a minimum width for a column using react-resizable and antd's table?如何使用 react-resizable 和 antd 的表格指定列的最小宽度?
【发布时间】:2019-09-06 12:53:12
【问题描述】:

我正在尝试使 antd 的表具有可调整大小的列。它运作良好。但是,当我调整列的大小时,我不能使任何列小于其内部文本。我尝试设置最小宽度,但它不起作用。至少在我的情况下。我相信应该有一些属性,我可以将其传递给可调整大小的组件以设置最小宽度。 我找到了示例 How antd table can work with react-resizable library。就在这里https://ant.design/components/table/ 但即使在这个例子中,它也和我的例子一样。

import React, { useState } from "react";
import { Button, Icon } from "antd";
import { Resizable } from "react-resizable";
import moment from "moment";
import UniqIdsGenerator from "lib/uniqIdsGenerator";
import SearchData from "containers/SearchData";
import { StyledTable, LikeLink, Header, SearchWrapper } from "./style";

const ResizeableTitle = props => {
    const { onResize, width, onClick, ...restProps } = props;

    const [allowClick, setAllowClick] = useState(true);

    if (!width) {
        return <th {...restProps} />;
    }

    return (
        <Resizable
            width={width}
            height={0}
            onResize={onResize}
            onMouseDown={e => {
                setAllowClick(true);
            }}
            onResizeStart={e => {
                setAllowClick(false);
            }}
            onClick={e => {
                if (allowClick && typeof onClick === "function") {
                    onClick(e);
                }
            }}
        >
            <th {...restProps} />
        </Resizable>
    );
};

const RowActions = ({ actions, uniqId, onRowAction, record, user }) =>
    actions.map(({ label, action }, fieldName) => {
        let { status } = record;
        return label === "log" && !statuses[status] ? null : (
            <LikeLink
                key={fieldName}
                id={uniqId.getTableRowAction(action)}
                onClick={e => {
                    e.preventDefault();
                    onRowAction({ record, action });
                }}
            >
                {label}
            </LikeLink>
        );
    });

const HeaderActions = ({ actions, handleClick, uniqId, isAllowed }) =>
    actions.map(({ label, action, icon }, fieldName) => {
        let button;
        label == "Add Upload" && !isAllowed
            ? (button = (
                  <Button
                      key={fieldName}
                      id={uniqId.getHeaderButton(fieldName)}
                      onClick={() => handleClick(action)}
                      disabled={true}
                      id={"disabledButton"}
                  >
                      {icon && <Icon type={icon} />}
                      {label}
                  </Button>
              ))
            : (button = (
                  <Button
                      key={fieldName}
                      id={uniqId.getHeaderButton(fieldName)}
                      onClick={() => handleClick(action)}
                  >
                      {icon && <Icon type={icon} />}
                      {label}
                  </Button>
              ));

        return button;
    });

class DataTable extends React.PureComponent {
    state = {
        columns: []
    };

    components = {
        header: {
            cell: ResizeableTitle
        }
    };

    uniqId = new UniqIdsGenerator(this.props.prefixId);

    componentDidMount() {
        const { handleClickOnTableRowAction } = this.props;
        this.getColumns({
            onRowAction: data => handleClickOnTableRowAction(data)
        });
    }

    handleResize = index => (e, { size }) => {
        this.setState(({ columns }) => {
            const nextColumns = [...columns];
            nextColumns[index] = {
                ...nextColumns[index],
                width: size.width
            };
            // console.log(size.width)
            return { columns: nextColumns };
        });
    };

    getColumns = ({ onRowAction }) => {
        const { columnsSchema, user } = this.props;
        const { uniqId } = this;

        let totalColumnsWidth = 250;

        const getTotalColumnWidth = column => {
            if (column.width) {
                totalColumnsWidth += column.width;
            }
        };

        const checkForWidth = column =>
            ((column.width && totalColumnsWidth) || column.isWidthFixed) &&
            column.width;

        const prepareToTable = (column, fieldName) => {
            return {
                title: column.label,
                dataIndex: column.fieldName,

                orgIndex: (text, record) => column.fieldName,
                key: column.key ? column.key : column.fieldName,
                width: checkForWidth(column),
                defaultSortOrder: column.defaultSortOrder,
                sorter: column.sortAs
                    ? (a, b) => sortAs[column.sortAs](a, b, column.fieldName)
                    : "",
                // filters: column.filters && column.filters,
                onFilter: (value, record) => record.traceType.match(value),
                // onHeaderCell: () => ({ 'id': uniqId.getTableTheadTh(fieldName) }),
                render: (text, record) => {
                    return {
                        props: {
                            id: uniqId.getTableTbodyTd(fieldName),
                            className: "classNameOfCell"
                        },
                        children: addChildren(column, record)
                    };
                }
            };
        };

        const addChildren = (column, record) => {
            if (column.render) {
                return column.render(record);
            } else if (column.actions) {
                return (
                    <RowActions
                        {...column}
                        user={user}
                        uniqId={this.uniqId}
                        onRowAction={onRowAction}
                        record={record}
                    />
                );
            }
            // }
            else {
                return record[column.fieldName];
            }
        };

        columnsSchema && columnsSchema.forEach(getTotalColumnWidth);

        const cols = columnsSchema.map(prepareToTable);

        // columnsSchema && columnsSchema.forEach(getTotalColumnWidth);

        const columns =
            cols &&
            cols.map((col, index) => ({
                ...col,
                onHeaderCell: column => ({
                    width: column.width,
                    onResize: this.handleResize(index)
                })
            }));

        columns && this.setState({ columns: columns });
    };

    render() {
        const {
            data,
            staticData,
            getRowKey,
            onSearch,
            loading,
            handleClickOnTableRowAction,
            handleClickOnHeaderButton,
            headerActionsSchema,
            isSearchDisabled,
            isAllowed
        } = this.props;

        const { uniqId } = this;
        const { columns } = this.state;

        return (
            <div id={uniqId.getComponentDivWrapper()}>
                <Header id={uniqId.getHeaderDiv()}>
                    {!isSearchDisabled && (
                        <SearchWrapper>
                            <SearchData
                                id={uniqId.getHeaderInput()}
                                placeholder="Search"
                                onSearch={e => onSearch(e, staticData)}
                            />
                        </SearchWrapper>
                    )}
                    <HeaderActions
                        actions={headerActionsSchema ? headerActionsSchema : []}
                        uniqId={uniqId}
                        handleClick={handleClickOnHeaderButton}
                        isAllowed={isAllowed}
                    />
                </Header>
                <div id={uniqId.getTableDivWrapper()}>
                    <StyledTable
                        loading={loading}
                        dataSource={data}
                        bordered
                        rowKey={getRowKey}
                        size="small"
                        pagination={{ pageSize: 10 }}
                        onRow={(row, fieldName) => ({
                            id: uniqId.getTableTbodyTr(fieldName)
                        })}
                        onHeaderRow={(row, fieldName) => ({
                            id: uniqId.getTableTheadTr(fieldName)
                        })}
                        components={this.components}
                        columns={columns}
                    />
                </div>
            </div>
        );
    }
}

export default DataTable;

【问题讨论】:

  • 请用codesandbox创建一个例子。需要组件from "./style";
  • @FiodorovAndrei:如果 foxer_bixer 在接下来的 7 天内不在线,您可以从 codepen.io/graham_saunders/pen/vrDxf 克隆可调整大小列的示例。

标签: reactjs antd


【解决方案1】:

指定列的最小宽度:

  1. 我们需要向列对象添加 minWidth 的新属性
columns: [
      {
        title: 'Date',
        dataIndex: 'date',
        width: 200,
        minWidth: 120
      },
]
  1. 我们将 column prop 向下传递:
const columns = this.state.columns.map((col, index) => ({
      ...col,
      onHeaderCell: column => ({
        minWidth: column.minWidth,
        width: column.width,
        onResize: this.handleResize(index)
      })
    }));
  1. 我们将 prop: minConstraints={[minWidth, 0]} 添加到 &lt;Resizable /&gt; 包装器

注意:同样适用于最大宽度,但我们将 maxWidth 属性传递给maxConstraints={[maxWidth, 0]}。此外,关于属性名称,我们可以为 minWidth 或 maxWidth 使用我们想要的任何名称。它们只是传递我们想要的数字的变量。

codesandbox 示例: https://codesandbox.io/s/minwidthresizable-cp25n

示例基于官方演示:https://ant.design/components/table/#components-table-demo-resizable-column

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    • 2021-02-18
    • 2018-08-19
    相关资源
    最近更新 更多