簡體   English   中英

有條件地反應表 select 行

[英]react-table conditionally select row

我們使用react-tableuseRowSelect進行行選擇。 我們想要擴展它,以便我們可以根據特定條件定義不可選擇的行,在這種情況下,它們將不可選擇——無論是單擊不可選擇的行還是單擊 Select All 時。

任何想法將不勝感激。

不知道你是否找到了答案,但我遇到了類似的問題。 您可以使用條件語句非常簡單地禁用行復選框。

在您的 useTable() 中,您將這樣的道具傳遞給您的復選框:

數據表.js

const {
    getTableProps,
    getTableBodyProps,
    headerGroups,
    rows,
    prepareRow,
    selectedFlatRows,
    state: { selectedRowIds },
} = useTable(
    {
    columns,
    data,
    
    initialState: {
      selectedRowIds: INITIAL_SELECTED_ROW_IDS
      
    }

    },
    useRowSelect,
    hooks => {
    hooks.visibleColumns.push(columns => [
        {
        id: 'selection',
        Header: ({ getToggleAllRowsSelectedProps }) => (
            <Checkbox {...getToggleAllRowsSelectedProps()} />
        ),
        Cell: ({ row }) => <><Checkbox {...row.getToggleRowSelectedProps()} {...row.values} />  </> 
//HERE : You pass your rows' values to your component
        },
        ...columns
    ])
    },
)

然后在您的復選框組件中,您可以根據您的道具之一判斷是否要禁用復選框(在這種情況下,我使用名為“valide”的行值之一)

CheckBox.js

import React, {useState} from 'react'

export const Checkbox = React.forwardRef(({ indeterminate, ...rest }, props, ref) => {
  const defaultRef = React.useRef()
  const resolvedRef = ref || defaultRef

  React.useEffect(() => {
    resolvedRef.current.indeterminate = indeterminate
  }, [resolvedRef, indeterminate])

  return (
    
    <div className="d-flex justify-content-around">
      {
      rest.Valide 
//i check if res.Valide is true or false (res.Valide is one of my row column's value which takes a boolean)
      ? <><input type='checkbox' ref={resolvedRef} {...rest} className="mx-auto" /></>
      : <><input type='checkbox' ref={resolvedRef} {...rest} className="mx-auto" disabled/></>
      }
    </div>
  )
})

如果 res.Valide 為 true,則該復選框正常呈現,否則它被禁用,因此您將無法檢查它。

通過調整最近在此 GitHub 問題中發布的答案,我設法提出了針對此問題的完整解決方案

就我而言,我需要它來處理分頁和 Select Page / Select All(而不是僅 Select All)。

我設法創建了一個解決方案——基於 GitHub 問題線程中的解決方案——它也支持這些要求。 然后我將它提取到一個易於重用的助手 function。 下面是幫助程序 function后面是使用示例

幫手 function

import { HeaderProps, Row } from 'react-table'

interface GetConditionalSelectHeaderCheckboxProps {
  /** react-table's header props */
  headerProps: React.PropsWithChildren<HeaderProps<any>>
  /** A predicate - based on your business logic - to determine whether a given row should be selectable */
  checkIfRowIsSelectable: (row: Row<any>) => boolean
  /** Whether to allow page selection. Default: true */
  shouldSelectPage?: boolean
}

/**
 * A convenience method for react-table headers for allowing conditional select
 * @param headerProps react-table's header props
 * @param checkIfRowIsSelectable A predicate - based on your business logic - to determine whether a given row should be selectable
 * @param shouldSelectPage Whether to allow page selection. Default: true
 * @returns Modified `checkboxProps` to enforce the conditional select
 */
export const getConditionalSelectHeaderCheckboxProps = ({
  headerProps,
  checkIfRowIsSelectable,
  shouldSelectPage = true,
}: GetConditionalSelectHeaderCheckboxProps) => {
  // Note that in my comments I differentiate between the standard logic and the logic for the conditional select
  const checkIfAllSelectableRowsSelected = (rows: Row<any>[]) =>
    rows.filter(checkIfRowIsSelectable).every(row => row.isSelected)
  // Standard: Here we define the selection type for the next click: Select Page / Select All
  const isSelectPage =
    shouldSelectPage &&
    headerProps.page
      // For conditional select: Filter the rows based on your business logic
      .filter(checkIfRowIsSelectable)
      // Standard: `isSelectPage === true` if some of the rows are not yet selected
      // This (standard) logic might be confusing to understand at first, but - as a side note - the idea is as follows:
      // This is the variable that defines whether the header props that will be received FOR THE NEXT CLICK will be for Select Page or for Select All
      // Try to play this out in your head:
      //  - Initially, none of the rows are selected, so when we clicking the button initially, we will select only the (selectable) rows on the page (i.e. Select Page), hence the next click will be for Select All, hence `isSelectPage` will be `false`
      //  - When clicking again, we will select the rest of the (selectable) rows (i.e. Select All). The next click will again be Select All (for de-selecting all), hence `isSelectPage` will be `false`
      //  - Finally, when clicking again, we will de-select all rows. The next click will be for Select Page, hence `isSelectPage` will `true`
      .some(row => !row.isSelected)

  // Standard: Get the props based on Select Page / Select All
  const checkboxProps = isSelectPage
    ? headerProps.getToggleAllPageRowsSelectedProps()
    : headerProps.getToggleAllRowsSelectedProps()

  // For conditional select: The header checkbox should be:
  //   - checked if all selectable rows are selected
  //   - indeterminate if only some selectable rows are selected (but not all)
  const disabled = headerProps.rows.filter(checkIfRowIsSelectable).length === 0
  const checked =
    !disabled && checkIfAllSelectableRowsSelected(headerProps.rows)
  const indeterminate = !checked && headerProps.rows.some(row => row.isSelected)

  // For conditional select: This is where the magic happens
  const onChange = () => {
    // If we're in Select All and all selectable rows are already selected: deselect all rows
    if (!isSelectPage && checkIfAllSelectableRowsSelected(headerProps.rows)) {
      headerProps.rows.forEach(row => {
        headerProps.toggleRowSelected(row.id, false)
      })
    } else {
      // Otherwise:
      // First, define the rows to work with: if we're in Select Page, use `headerProps.page`, otherwise (Select All) use headerProps.rows
      const rows = isSelectPage ? headerProps.page : headerProps.rows
      // Then select every selectable row
      rows.forEach(row => {
        const checked = checkIfRowIsSelectable(row)
        headerProps.toggleRowSelected(row.id, checked)
      })
    }
  }

  // For conditional select: override checked, indeterminate and onChange - to enforce conditional select based on our business logic
  return {
    ...checkboxProps,
    checked,
    indeterminate,
    onChange,
    disabled,
  }
}

示例用法:

const columns = [
    {
        accessor: 'foo',
        Header(props) {
            const checkboxProps = getConditionalSelectHeaderCheckboxProps({
                headerProps: props,
                // Your business logic, e.g.
                checkIfRowIsSelectable: row => row.original.someData !== 'some value'
            })

            return <Checkbox {...checkboxProps} />
        },
    // ...
]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM