【问题标题】:How do I add column sort functionality to my table?如何将列排序功能添加到我的表中?
【发布时间】:2017-09-19 12:53:21
【问题描述】:

我已经尝试了几个小时在 react-virtualized 表上添加排序功能,但无法理解它......这里是 examplesource code。抱歉,我无法创建 plnkr,所以我附上了一个链接到我的 github repo

当我提交带有输入文本 SCREW 的表单时出现此错误,例如:

TypeError: list.sortBy is not a function
    at PartTable._sortList (PartTable.js:136)
    at new PartTable (PartTable.js:18)

site 的示例中,他们使用上下文(const { list } = this.context;)而不是道具。也许这就是问题所在?

当我在控制台登录 this.props.list 时,我得到了正确的列表(参见两个示例文档)

_sortList({ sortBy, sortDirection }) {
    const { list } = this.props;

    // console.log(list);

    return list
      .sortBy(item => item[sortBy])
      .update(
        list => (sortDirection === SortDirection.DESC ? list.reverse() : list)
      );
  }

这里有两个对象来自我的服务器并进入props.list

[
  {
    customsTariff: "73181568",
    facility: "SDC",
    netWeight: "0,07",
    partName: "CAPSCREW",
    partNumber: "3121210233",
    __v: 0,
    _id: "59a9429ac0b7467bf084eb6e"
  },
  {
    customsTariff: "73481568",
    facility: "SDC",
    netWeight: "0,08",
    partName: "CAPSCREW2",
    partNumber: "3121210333",
    __v: 0,
    _id: "59a9429ac0b7463bf084eb6e"
  }
];

这是来自 PartTable.js 的代码

import React, { PureComponent } from "react";
import { AutoSizer, Column, Table } from "react-virtualized";
import { CSVLink, CSVDownload } from "react-csv";
import Button from "material-ui/Button";
import PropTypes from "prop-types";
import SortDirection from "./SortDirection";
import SortIndicator from "./SortIndicator";
import Checkbox from "material-ui/Checkbox";
import "react-virtualized/styles.css";
import "../../styles/App.css";
import styles from "./Table.example.css";

export default class PartTable extends PureComponent {
  constructor(props) {
    super(props);
    const sortBy = "partNumber"; // I want to sort by partNumber by default
    const sortDirection = SortDirection.ASC;
    const sortedList = this._sortList({ sortBy, sortDirection });

    this.state = {
      sortBy,
      sortDirection,
      rowCount: 1000,
      sortedList
    };
    this._noRowsRenderer = this._noRowsRenderer.bind(this);
    this._generateCheckbox = this._generateCheckbox.bind(this);
    this._sort = this._sort.bind(this);
  }

  render() {
    // console.log(this.props.list);
    const { sortBy, sortDirection, sortedList } = this.state;
    const rowGetter = ({ index }) => this._getDatum(sortedList, index);
    const { list, headers } = this.props;
    return (
      <div>
        <AutoSizer disableHeight>
          {({ width }) => (
            <Table
              width={width}
              height={500}
              headerHeight={50}
              rowHeight={50}
              rowCount={list.length}
              rowGetter={rowGetter}
              noRowsRenderer={this._noRowsRenderer}
              sort={this._sort}
              sortBy={sortBy}
              sortDirection={sortDirection}
            >
              {headers.map(header => {
                return (
                  <Column
                    key={header.id}
                    label={header.label}
                    dataKey={header.id}
                    disableSort
                    width={100}
                    flexGrow={1}
                    cellRenderer={
                      header.index ? this._generateCheckbox : undefined
                    }
                  />
                );
              })}
            </Table>
          )}
        </AutoSizer>
        <CSVLink data={list}>
          <Button color="accent">Export {list.length} records to CSV</Button>
        </CSVLink>
      </div>
    );
  }

  _noRowsRenderer() {
    return <div>No Parts here...</div>;
  }
  _generateCheckbox(event) {
    // console.log(event);
    return (
      <div className="table-check-box">
        {this.props.activeCheckboxes && (
          <Checkbox
            onChange={() => this.props._activeCheckbox(event.rowData._id)}
            checked={this.props.activeCheckboxes.includes(event.rowData._id)}
          />
        )}
        {event.cellData}
      </div>
    );
  }
  _isSortEnabled() {
    const { list } = this.props;
    const { rowCount } = this.state;
    return rowCount <= list.size;
  }

  _getDatum(list, index) {
    return list.get(index % list.size);
  }

  _sort({ sortBy, sortDirection }) {
    const sortedList = this._sortList({ sortBy, sortDirection });

    this.setState({ sortBy, sortDirection, sortedList });
  }

  _sortList({ sortBy, sortDirection }) {
    const { list } = this.props;

    // console.log(list);

    return list
      .sortBy(item => item[sortBy])
      .update(
        list => (sortDirection === SortDirection.DESC ? list.reverse() : list)
      );
  }
  _rowClassName({ index }) {
    if (index < 0) {
      return styles.headerRow;
    } else {
      return index % 2 === 0 ? styles.evenRow : styles.oddRow;
    }
  }
}

PartTable.PropTypes = {
  list: PropTypes.arrayOf({}).isRequired,
  activeCheckboxes: PropTypes.arrayOf({}),
  _activeCheckbox: PropTypes.func,
  headers: PropTypes.arrayOf({}.isRequired)
};

【问题讨论】:

    标签: javascript reactjs react-virtualized


    【解决方案1】:

    基于您的代码引用了 list.length 的事实 - 您接受的 list 道具似乎是一个数组? sortBy 方法(假设您是从 react-virtualized 文档中提取的)属于 Immutable JS List。要对 JavaScript 数组进行排序,您需要使用 Array.prototype.sort

    PS。您粘贴的代码还有一些对List 方法(例如list.get(index))的其他引用,如果您使用的是数组,您需要用括号(例如list[index])替换它们。

    PartTable.js 的完整代码解决方案 (作者提供)

    import React, { PureComponent } from "react";
    import {
      AutoSizer,
      Column,
      Table,
      SortDirection,
      SortIndicator
    } from "react-virtualized";
    import { CSVLink, CSVDownload } from "react-csv";
    import Button from "material-ui/Button";
    import PropTypes from "prop-types";
    import Checkbox from "material-ui/Checkbox";
    import "react-virtualized/styles.css";
    import "../../styles/App.css";
    import styles from "./Table.example.css";
    
    export default class PartTable extends PureComponent {
      constructor(props) {
        super(props);
    
        const sortBy = "partNumber";
        const sortDirection = SortDirection.ASC;
        const sortedList = this._sortList({ sortBy, sortDirection });
    
        this.state = {
          list: this.props.list,
          sortBy,
          sortDirection,
          sortedList,
          rowCount: 1000
        };
        this._noRowsRenderer = this._noRowsRenderer.bind(this);
        this._generateCheckbox = this._generateCheckbox.bind(this);
        this._sort = this._sort.bind(this);
      }
    
      render() {
        const { headers } = this.props;
        const { list, sortBy, sortDirection, sortedList, rowCount } = this.state;
    
        const rowGetter = ({ index }) => this._getDatum(sortedList, index);
    
        return (
          <div>
            <AutoSizer disableHeight>
              {({ width }) => (
                <Table
                  width={width}
                  height={500}
                  headerHeight={50}
                  rowHeight={50}
                  rowClassName={this._rowClassName}
                  rowCount={rowCount}
                  rowGetter={({ index }) => list[index]} // ({ index }) => list[index]
                  noRowsRenderer={this._noRowsRenderer}
                  onHeaderClick={this._sortByClickedHeader}
                  sort={this._sort}
                  sortBy={sortBy}
                  sortDirection={sortDirection}
                >
                  {headers.map(header => {
                    return (
                      <Column
                        key={header.id}
                        label={header.label}
                        dataKey={header.id}
                        width={100}
                        flexGrow={1}
                        cellRenderer={
                          header.index ? this._generateCheckbox : undefined
                        }
                      />
                    );
                  })}
                </Table>
              )}
            </AutoSizer>
            <CSVLink data={list}>
              <Button color="accent">Export {list.length} records to CSV</Button>
            </CSVLink>
          </div>
        );
      }
    
      _getDatum(list, index) {
        return list[index];
      }
    
      _sort({ sortBy, sortDirection }) {
        const sortedList = this._sortList({ sortBy, sortDirection });
    
        this.setState({ sortBy, sortDirection, sortedList });
      }
    
      _sortList({ sortBy, sortDirection }) {
        const { list } = this.props;
        if (sortBy) {
          let updatedList =
            // sort by name
            list.sort(function(a, b) {
              var nameA = a[sortBy].toUpperCase(); // ignore upper and lowercase
              var nameB = b[sortBy].toUpperCase(); // ignore upper and lowercase
              if (nameA < nameB) {
                return -1;
              }
              if (nameA > nameB) {
                return 1;
              }
              // names must be equal
              return 0;
            });
          sortDirection === SortDirection.DESC
            ? updatedList.reverse()
            : updatedList;
        }
      }
    
      _noRowsRenderer() {
        return <div>No Parts here...</div>;
      }
      _generateCheckbox(event) {
        // console.log(event);
        return (
          <div className="table-check-box">
            {this.props.activeCheckboxes && (
              <Checkbox
                onChange={() => this.props._activeCheckbox(event.rowData._id)}
                checked={this.props.activeCheckboxes.includes(event.rowData._id)}
              />
            )}
            {event.cellData}
          </div>
        );
      }
    }
    
    PartTable.PropTypes = {
      list: PropTypes.arrayOf({}).isRequired,
      activeCheckboxes: PropTypes.arrayOf({}),
      _activeCheckbox: PropTypes.func,
      headers: PropTypes.arrayOf({}.isRequired)
    };
    

    【讨论】:

      猜你喜欢
      • 2014-08-25
      • 1970-01-01
      • 1970-01-01
      • 2019-10-25
      • 2018-06-29
      • 2013-11-20
      • 1970-01-01
      • 2015-08-12
      • 1970-01-01
      相关资源
      最近更新 更多