javascript - 列上的默认过滤器值

标签 javascript reactjs react-table

我认为我缺少一些 React 或 JavaScript 知识来解决我想做的事情。

背景:

  • 我有一个用 React Table 制作的表格。
  • 每列都有一个输入框过滤器。组件中的状态自动接收查询字符串并将其解析为对象。当页面加载已解析的查询字符串时,输入框会自动填充。
  • 但是,表格中显示的数据仍然是所有数据,而不仅仅是过滤后的数据。我必须浏览每个输入框并按 Enter 键才能按该值进行过滤。所以输入框中自动输入的值只是为了显示

我的问题:

我希望在加载时过滤表。但我不知道如何在加载所有内容后触发过滤器。

列标题代码:

//    ***Generate the column structure necessary for ReactTable
generateColumnHeaders(api_part_labels) {
    let label_array = []
    for (var key in api_part_labels) {
        const hasHeader = api_part_labels[key].includes(">")

        if (hasHeader) {
            label_array.push([api_part_labels[key].split(">")[0], api_part_labels[key].split(">")[1], key]);
        } else {
            label_array.push([api_part_labels[key], api_part_labels[key], key]);
        }
    }
    let mainHeaders = label_array.map((x) => x[0]);
    mainHeaders = Array.from(new Set(mainHeaders));
    let output = [];
    console.log(this.state.parsed);
    for (var i in mainHeaders) {
        let labels = label_array.filter(x => x[0] === mainHeaders[i]);

        if (labels.length === 1) {
            let param = labels[0][2];
            output.push({
                Header: labels[0][1],
                accessor: param,
                id: param,
                width: this.calculateColumnWidth(param, labels[0][1]),

            });
        } else {
            let columns = [];
            for (var i_label in labels) {
                var label = labels[i_label];
                let param = label[2];
                columns.push({
                    Header: label[1],
                    accessor: param,
                    id: param,
                    width: this.calculateColumnWidth(param, label[1]),
                    filteredValue: this.state.parsed[param],
                    Filter: ({ filter, onChange }) => {
                        return (
                            <input
                                onKeyPress={event => {
                                    if (event.keyCode === 13 || event.which === 13) {
                                        let value = event.target.value;
                                        onChange(value);

                                        // update the parsed state with the event filter value
                                        this.updateParsed(param, value);

                                        // update 1) the query string, and 2) the URL
                                        let stringified = queryString.stringify(this.state.parsed);
                                        this.props.location.search = stringified;
                                        this.props.history.push(`?${stringified}`);
                                    }
                                }}
                                defaultValue={this.state.parsed[param]}
                            />
                        )},
                });
            }
            output.push({ Header: labels[0][0], columns: columns });
        }
    }

    return output;
};

我的 react 表:

return (
            <ReactTable
                // data and columns
                data = { this.parts }
                noDataText = "Whoops! No data available!"
                columns = { this.part_columns }

                // appearance
                defaultPageSize = {20}
                className = "-striped -highlight"
                style = {{ height: "800px" }}

                // sorting and filtering
                defaultSorted = {[ { id: "part_number", desc: false } ]}
                filterable
                defaultFilterMethod = {(filter, row) =>

String(row[filter.id]).toLowerCase().includes(filter.value.toLowerCase())}
            />
        )

最佳答案

我认为你需要 ReactTable 上的 defaultFiltered 属性:

            defaultFiltered={[
              {
                id: 'reporting_year',
                value: new Date().getFullYear(),
              },
            ]}

我还想将过滤框中的编辑控件自定义为包含列中唯一值的下拉列表。由于文档非常薄弱(或者我很慢和/或迟到了),我也会在此处包含列定义:

    {
      Header: 'Report Yr',
      accessor: 'reporting_year',
      Filter: ({ filter, onChange }) => {
        let found = {}
        let options = this.props.dashboard
          // remove duplicates
          .filter(function(row) {
            if (!found[row.reporting_year]) {
              found[row.reporting_year] = true
              return true
            }
            return false
          })
          // sort
          .sort((a, b) => (a.reporting_year > b.reporting_year ? 1 : b.reporting_year > a.reporting_year ? -1 : 0))
          // return option list
          .map(function(row) {
            return (
              <option value={row.reporting_year} key={row.reporting_year}>
                {row.reporting_year}
              </option>
            )
          })
        return (
          <select
            onChange={event => {
              onChange(event.target.value)
            }}
            style={{ width: '100%' }}
            value={filter ? filter.value : 'all'}>
            {options}
          </select>
        )
      },
    },

默认过滤器文本框被替换为包含数据中所有值的下拉列表,默认为 defaultFiltered 设置(在本例中为当前年份)。

请注意,如果您不需要“全部”选项,则此演示文稿效果不佳,因为该列只能包含单个值,因此会浪费水平屏幕空间。

为了避免为每一列重复代码,我创建了一个高阶函数。这非常方便 - 只需在任何列上设置 FilterfilterMethod 属性即可将文本过滤器切换到包含所有唯一值的下拉列表。

class MyCmp extends Component {
  ...
  filterFn = accessor => ({ filter, onChange }) => {
    let found = {}
    let options = this.props.dashboard
      .filter(function(row) {
        if (row[accessor] && !found[row[accessor]]) {
          found[row[accessor]] = true
          return true
        }
        return false
      })
      .sort((a, b) => (a[accessor] > b[accessor] ? 1 : b[accessor] > a[accessor] ? -1 : 0))
      .map(function(row) {
        return (
          <option value={row[accessor]} key={row[accessor]}>
            {row[accessor]}
          </option>
        )
      })
    return (
      <select
        onChange={event => {
          onChange(event.target.value)
        }}
        style={{ width: '100%' }}
        value={filter ? filter.value : 'all'}>
        <option value='all' key={'all'}>
          All
        </option>
        {options}
      </select>
    )
  }
  filterMethod = (filter, row, column) => {
    if (filter.value === 'all') {
      return true
    }
    const id = filter.pivotId || filter.id
    return row[id] !== undefined ? String(row[id]) === String(filter.value) : true
  }

然后,要将下拉列表添加到列,只需添加 FilterfilterMethod 属性:

  columns = [
    {
      Header: 'CSP Code',
      accessor: 'csp_code',
      Filter: this.filterFn('csp_code'),
      filterMethod: this.filterMethod,
    },
    {
      Header: 'Report Yr',
      accessor: 'reporting_year',
      Filter: this.filterFn('reporting_year'),
      filterMethod: this.filterMethod,
    },
    ...

请注意,这会忽略空单元格 - 它们仅在选择“全部”时显示,并且无法进行过滤。此外,例如,它不区分“12”和 12。它还忽略基础值上的自定义单元格和过滤器 - 我的一些单元格是图标,但下拉列表显示并过滤基础数据值(这对我来说是期望的行为,并且充当图标的一种键) .

This example有一些方便的代码示例和技术。

关于javascript - 列上的默认过滤器值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52659961/

相关文章:

javascript - 在 react 中创建扩展默认 PropTypes 的自定义 PropTypes

node.js - 我无法使用 npx 创建 react 应用程序

css - React-Table列固定宽度破坏了整个表格

javascript - React 表出现问题 TypeError : Cannot read property 'forEach' of undefined

javascript - Math.pow 给出了错误的结果

javascript - Jquery 一次拖动所有项目

javascript - 句子的正确顺序

reactjs - 继承ReasonReact中的Nextjs App组件(pages/_app.js)

javascript - 观察现有对象的对象属性变化

reactjs - 在 Vue.js 中使用 React-table.js 时出错