【问题标题】:Select row on click react-table在单击反应表上选择行
【发布时间】:2017-12-04 08:23:25
【问题描述】:

我正在努力寻找与我的 react 应用程序一起使用的最佳表格,目前,react-table 提供了我需要的一切(分页、服务器端控制、过滤、排序、页脚行)。

话虽如此,我似乎无法选择一行。没有 examples 显示这一点。

我尝试过的一些事情包括尝试在单击该行时设置一个类名。但我似乎无法在e 和t 中找到调用元素。另外,我不喜欢这种方法,因为 React 应用不应该这样做。

<ReactTable
            ...
            getTrProps={(state, rowInfo, column, instance) => {
                return {
                    onClick: (e, t) => {
                        t.srcElement.classList.add('active')
                    },
                    style: {
                    }
                }
            }}
        />

一些可能的解决方法是将复选框呈现为第一列,但这不是最佳选择,因为它限制了单击区域以“激活”该行。此外,视觉反馈的表现力也会降低。

我想念房间里的大象吗?如果没有,您知道另一个支持我之前描述的东西的库吗?

谢谢!

编辑: 另一种选择,这是开源的,是建议编辑。也许这是正确的做法。

编辑 2

Davorin Ruševljan 在 cmets 中提出的另一件事是:

onRowClick(e, t, rowInfo) {
    this.setState((oldState) => {
        let data = oldState.data.slice();
        let copy = Object.assign({},  data[rowInfo.index]);

        copy.selected = true;
        copy.FirstName = "selected";
        data[rowInfo.index] = copy;

        return {
            data: data,
        }
    })
}

....

            getTrProps={(state, rowInfo, column) => {
                return {
                    onClick: (e, t) => { this.onRowClick(e, t, rowInfo) },
                    style: {
                        background: rowInfo && rowInfo.row.selected ? 'green' : 'red'
                    }
                }
            }}

这会将“FirstName”列设置为“selected”,但不会将类设置为“green”

【问题讨论】:

    标签: reactjs react-table


    【解决方案1】:

    经过几次尝试,我找到了解决方案,希望对您有所帮助。将以下内容添加到您的 &lt;ReactTable&gt; 组件中:

    getTrProps={(state, rowInfo) => {
      if (rowInfo && rowInfo.row) {
        return {
          onClick: (e) => {
            this.setState({
              selected: rowInfo.index
            })
          },
          style: {
            background: rowInfo.index === this.state.selected ? '#00afec' : 'white',
            color: rowInfo.index === this.state.selected ? 'white' : 'black'
          }
        }
      }else{
        return {}
      }
    }
    

    在您的state 中不要忘记添加一个空的selected 值,例如:

    state = { selected: null }
    

    【讨论】:

    • 这个可以多选吗?
    • 也为我工作,但我还必须检查 rowinfo !== undefined 以避免运行时错误
    • @YoungScooter 你用this 影响了that 吗?你更新点击状态了吗?
    • @ConstantinGuidon 抱歉回复晚了。找到链接了,就在这里! github.com/react-tools/react-table/issues/233
    • 嗨,有人能解释一下我的 rowInfo 是如何被定义为未定义的吗?我不确定如何正确使用getTrProps 方法
    【解决方案2】:

    React-Table 包含一个允许选择的 HOC,即使在过滤和分页表格时,设置也比基本表格稍微高级一些,因此请先阅读下面链接中的信息。




    导入 HOC 后,您可以通过必要的方法像这样使用它:

    /**
    * Toggle a single checkbox for select table
    */
    toggleSelection(key: number, shift: string, row: string) {
        // start off with the existing state
        let selection = [...this.state.selection];
        const keyIndex = selection.indexOf(key);
    
        // check to see if the key exists
        if (keyIndex >= 0) {
            // it does exist so we will remove it using destructing
            selection = [
                ...selection.slice(0, keyIndex),
                ...selection.slice(keyIndex + 1)
            ];
        } else {
            // it does not exist so add it
            selection.push(key);
        }
        // update the state
        this.setState({ selection });
    }
    
    /**
    * Toggle all checkboxes for select table
    */
    toggleAll() {
        const selectAll = !this.state.selectAll;
        const selection = [];
    
        if (selectAll) {
            // we need to get at the internals of ReactTable
            const wrappedInstance = this.checkboxTable.getWrappedInstance();
            // the 'sortedData' property contains the currently accessible records based on the filter and sort
            const currentRecords = wrappedInstance.getResolvedState().sortedData;
            // we just push all the IDs onto the selection array
            currentRecords.forEach(item => {
                selection.push(item._original._id);
            });
        }
        this.setState({ selectAll, selection });
    }
    
    /**
    * Whether or not a row is selected for select table
    */
    isSelected(key: number) {
        return this.state.selection.includes(key);
    }
    
    <CheckboxTable
        ref={r => (this.checkboxTable = r)}
        toggleSelection={this.toggleSelection}
        selectAll={this.state.selectAll}
        toggleAll={this.toggleAll}
        selectType="checkbox"
        isSelected={this.isSelected}
        data={data}
        columns={columns}
    />
    

    请参阅此处了解更多信息:
    https://github.com/tannerlinsley/react-table/tree/v6#selecttable

    这是一个工作示例:
    https://codesandbox.io/s/react-table-select-j9jvw

    【讨论】:

    • 这似乎是最好的方法。 react-table 通过这个高阶组件支持选择。
    【解决方案3】:

    如果你想在选择行上进行多项选择..

    import React from 'react';
    import ReactTable from 'react-table';
    import 'react-table/react-table.css';
    import { ReactTableDefaults } from 'react-table';
    import matchSorter from 'match-sorter';
    
    
    class ThreatReportTable extends React.Component{
    
    constructor(props){
      super(props);
    
      this.state = {
        selected: [],
        row: []
      }
    }
    render(){
    
      const columns = this.props.label;
    
      const data = this.props.data;
    
      Object.assign(ReactTableDefaults, {
        defaultPageSize: 10,
        pageText: false,
        previousText: '<',
        nextText: '>',
        showPageJump: false,
        showPagination: true,
        defaultSortMethod: (a, b, desc) => {
        return b - a;
      },
    
    
      })
    
        return(
        <ReactTable className='threatReportTable'
            data= {data}
            columns={columns}
            getTrProps={(state, rowInfo, column) => {
    
    
            return {
              onClick: (e) => {
    
    
                var a = this.state.selected.indexOf(rowInfo.index);
    
    
                if (a == -1) {
                  // this.setState({selected: array.concat(this.state.selected, [rowInfo.index])});
                  this.setState({selected: [...this.state.selected, rowInfo.index]});
                  // Pass props to the React component
    
                }
    
                var array = this.state.selected;
    
                if(a != -1){
                  array.splice(a, 1);
                  this.setState({selected: array});
    
    
                }
              },
              // #393740 - Lighter, selected row
              // #302f36 - Darker, not selected row
              style: {background: this.state.selected.indexOf(rowInfo.index) != -1 ? '#393740': '#302f36'},
    
    
            }
    
    
            }}
            noDataText = "No available threats"
            />
    
        )
    }
    }
    
    
      export default ThreatReportTable;
    

    【讨论】:

      【解决方案4】:

      您选择的答案是正确的,但是如果您使用排序表,它将崩溃,因为您搜索时 rowInfo 将变得未定义,建议您改用此函数

                      getTrGroupProps={(state, rowInfo, column, instance) => {
                          if (rowInfo !== undefined) {
                              return {
                                  onClick: (e, handleOriginal) => {
                                    console.log('It was in this row:', rowInfo)
                                    this.setState({
                                        firstNameState: rowInfo.row.firstName,
                                        lastNameState: rowInfo.row.lastName,
                                        selectedIndex: rowInfo.original.id
                                    })
                                  },
                                  style: {
                                      cursor: 'pointer',
                                      background: rowInfo.original.id === this.state.selectedIndex ? '#00afec' : 'white',
                                      color: rowInfo.original.id === this.state.selectedIndex ? 'white' : 'black'
                                  }
                              }
                          }}
                      }
      

      【讨论】:

        【解决方案5】:

        我不熟悉 react-table,所以我不知道它是否直接支持选择和取消选择(如果有就好了)。

        如果没有,您可以使用已有的代码安装 onCLick 处理程序。现在,您可以修改状态,而不是尝试将样式直接附加到行,例如通过将 selected: true 添加到行数据。这将触发重新渲染。现在您只需要覆盖带有 selected === true 的行是如何呈现的。类似的东西:

        // Any Tr element will be green if its (row.age > 20) 
        <ReactTable
          getTrProps={(state, rowInfo, column) => {
            return {
              style: {
                background: rowInfo.row.selected ? 'green' : 'red'
              }
            }
          }}
        />
        

        【讨论】:

        • 感谢您的重播,@Davorin!我认为这没有任何用处,因为我无法控制表的状态,因此我无法设置 rowInfo.row.selected.. 如果不调用 this.setState,表将不会重新呈现
        • 你的意思是你没有控制权,你正在为表提供数据属性,在数据中更改它
        • 我的意思是当数据发生变化时,getTrProps 不是页面重新呈现的一部分。不幸的是,将新数据设置到表中并不会调用它。我将按照我尝试的方式编辑我的问题。
        【解决方案6】:

        动态样式的另一种机制是在 JSX 中为您的组件定义它。例如,以下内容可用于选择性地设置 React tic-tac-toe 教程中当前步骤的样式(建议的额外信用增强之一:

          return (
            <li key={move}>
              <button style={{fontWeight:(move === this.state.stepNumber ? 'bold' : '')}} onClick={() => this.jumpTo(move)}>{desc}</button>
            </li>
          );
        

        当然,更简洁的方法是添加/删除“选定”的 CSS 类,但这种直接方法在某些情况下可能会有所帮助。

        【讨论】:

          【解决方案7】:

          带有复选框的多行并使用useState() 钩子选择所有行。需要少量实现以适应自己的项目。

              const data;
              const [ allToggled, setAllToggled ] = useState(false);
              const [ toggled, setToggled ] = useState(Array.from(new Array(data.length), () => false));
              const [ selected, setSelected ] = useState([]);
          
              const handleToggleAll = allToggled => {
                  let selectAll = !allToggled;
                  setAllToggled(selectAll);
                  let toggledCopy = [];
                  let selectedCopy = [];
                  data.forEach(function (e, index) {
                      toggledCopy.push(selectAll);
                      if(selectAll) {
                          selectedCopy.push(index);
                      }
                  });
                  setToggled(toggledCopy);
                  setSelected(selectedCopy);
              };
          
              const handleToggle = index => {
                  let toggledCopy = [...toggled];
                  toggledCopy[index] = !toggledCopy[index];
                  setToggled(toggledCopy);
                  if( toggledCopy[index] === false ){
                      setAllToggled(false);
                  }
                  else if (allToggled) {
                      setAllToggled(false);
                  }
              };
          
          ....
          
          
                          Header: state => (
                              <input
                                  type="checkbox"
                                  checked={allToggled}
                                  onChange={() => handleToggleAll(allToggled)}
                              />
                          ),
                          Cell: row => (
                              <input
                                  type="checkbox"
                                  checked={toggled[row.index]}
                                  onChange={() => handleToggle(row.index)}
                              />
                          ),
          
          ....
          
          <ReactTable
          
          ...
                              getTrProps={(state, rowInfo, column, instance) => {
                                  if (rowInfo && rowInfo.row) {
                                      return {
                                          onClick: (e, handleOriginal) => {
                                              let present = selected.indexOf(rowInfo.index);
                                              let selectedCopy = selected;
          
                                              if (present === -1){
                                                  selected.push(rowInfo.index);
                                                  setSelected(selected);
                                              }
          
                                              if (present > -1){
                                                  selectedCopy.splice(present, 1);
                                                  setSelected(selectedCopy);
                                              }
          
                                              handleToggle(rowInfo.index);
                                          },
                                          style: {
                                              background: selected.indexOf(rowInfo.index)  > -1 ? '#00afec' : 'white',
                                              color: selected.indexOf(rowInfo.index) > -1 ? 'white' : 'black'
                                          },
                                      }
                                  }
                                  else {
                                      return {}
                                  }
                              }}
          />
          

          【讨论】:

            【解决方案8】:
            # react-table with edit button #
            const [rowIndexState, setRowIndexState] = useState(null);
            const [rowBackGroundColor, setRowBackGroundColor] = useState('')
            {...row.getRowProps({
              onClick: (e) => {
                if (!e.target.cellIndex) {
                   setRowIndexState(row.index);
                   setRowBackGroundColor('#f4f4f4')
                }
              },
              style: {
               background: row.index === rowIndexState ? rowBackGroundColor : '',
              },              
            })}
            

            【讨论】:

              猜你喜欢
              • 2018-10-16
              • 2021-09-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-12-03
              • 2023-01-17
              • 1970-01-01
              相关资源
              最近更新 更多