列上的默认过滤器值

时间:2018-10-05 06:58:17

标签: 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())}
            />
        )

5 个答案:

答案 0 :(得分:0)

您需要调用一个函数来在componentDidMount()方法内过滤表的数据。

如果您不知道什么是compoenetDidMount()方法,请阅读有关Lifecycle Events in React的指南,这是在React中理解以基于文档的触发事件实现某些操作的核心概念之一。

答案 1 :(得分:0)

如@Elharony所述,您需要设置componentDidMount()方法中的按查询项过滤的功能-我已经为您完成了代码here,请参见注释。

希望这会有所帮助!

答案 2 :(得分:0)

看看这个example。您需要在页面加载时设置filtered={filteredData},并且可能需要按照FAQ

中的说明处理onFilteredChange
  

如果打算将外部排序/过滤与表中用户驱动的输入混合使用,则还需要考虑处理onFilteredChange和onSortedChange。您的代码将需要聪明地决定输入(程序输入还是用户输入)优先。

答案 3 :(得分:0)

我认为您需要在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设置(在本例中为当前年份)。

请注意,如果您不希望使用All选项,那么此演示文稿就不好了,因为该列只能包含一个值,所以浪费了水平屏幕空间。

为避免为每一列重复代码,我创建了一个高阶函数。这非常方便-只需在任意列上设置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有一些方便的代码示例和技术。

答案 4 :(得分:-1)

尝试在加载数据后呈现表。您可以添加简单的加载程序(默认情况下已打开),加载数据,并在成功加载后关闭加载程序。仅在关闭加载程序时才渲染表。