coreui/coreui-react

Fields `_id` & `_selected` are not present after selecting rows in CSmartTable component

Alan-Graton opened this issue · 1 comments

Error Description

EDIT: I just added the selected prop in my CSmartTable with the spected fields (Items[] type) but still not working ;-;

I just upgraded my CoreUI packages in order to use enhanced filters in my CSmartTables. Before upgrading I was able to set a table as selectable/or not and select my items normaly.

If I logged the selected Items I would get:

{
 // .. rest of my data
 "_id": 0,
 "_selected": true
}

After upgrading these 2 fields were gone, and I was using them for some status control (what should be selected or not). This afected all my CSmartTables in my application ;-;

If I downgrade my CoreUI packages versions I lose my new filters but I can use my previous selection logic.

Here is my CSmartTable:

image

With the upgrades I was able to set a CFormSelect on my Dates columns following the docs. In this case, all Not Approved lines should be the only ones to be selected.

Dependencies

"dependencies": {
    "@aws-amplify/ui-react": "^2.16.2",
    "@coreui/chartjs": "^3.1.2",
    "@coreui/coreui": "^4.3.0",
    "@coreui/icons": "^3.0.1",
    "@coreui/icons-react": "^2.2.1",
    "@coreui/react": "^4.9.2",
    "@coreui/react-chartjs": "^2.1.3",
    "@coreui/react-pro": "^4.12.4",
    "@coreui/utils": "^1.3.1",
    "@emotion/react": "^11.10.4",
    "@emotion/styled": "^11.10.4",
    "@mui/material": "^5.10.8",
    "@mui/x-date-pickers": "^5.0.3",
    "aws-amplify": "^4.3.21",
    "chart.js": "^3.7.1",
    "date-fns": "^2.30.0",
    "dayjs": "^1.11.5",
    "exceljs": "^4.3.0",
    "prop-types": "^15.8.1",
    "react": "^17.0.2",
    "react-app-polyfill": "^3.0.0",
    "react-date-picker": "^8.4.0",
    "react-dom": "^17.0.2",
    "react-input-date-mask": "^2.0.0",
    "react-input-mask": "^2.0.4",
    "react-loading-skeleton": "^3.1.0",
    "react-redux": "^7.2.6",
    "react-router-dom": "^6.11.2",
    "react-spinners": "^0.13.4",
    "react-toastify": "^9.0.5",
    "redux": "4.2.0",
    "simplebar-react": "^2.3.7",
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^12.1.3",
    "@testing-library/user-event": "^13.5.0",
    "auto-changelog": "~2.4.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.0.0",
    "prettier": "2.6.2",
    "react-scripts": "5.0.1",
    "sass": "^1.51.0",
    "web-vitals": "^2.1.4"
  },

Code

I created a Global CSmartTable which I used on the previous picture. Here is the React Component:

import React from 'react'
import { CSmartTable } from '@coreui/react-pro'

import PropTypes from 'prop-types'

// Styles
import './styles.css'

export default function GlobalSmartTable({
  items,
  loading,
  selectable,
  handleSelectedItemsChange,
  columns,
  selectedRows,
  setSelectedRows,
  scopedColumns,
  customFilter,
}) {
  const [tableColumns, setTableColumns] = React.useState(columns)

  // Setting Table Columns
  React.useEffect(() => {
    if (customFilter && tableColumns?.every((index) => index !== undefined)) {
      setTableColumns(customFilter(tableColumns))
    }
  }, [items])

  return (
    <>
      <CSmartTable
        activePage={1}
        loading={loading}
        items={items}
        columns={columns}
        cleaner
        columnFilter
        columnSorter
        selected={selectedRows}
        selectable={selectable}
        onSelectedItemsChange={(items) => {
          handleSelectedItemsChange(items, setSelectedRows)
        }}
        scopedColumns={scopedColumns}
        noItemsLabel="Nothing found"
        tableFilter
        tableFilterLabel=""
        tableFilterPlaceholder="Search..."
        itemsPerPageSelect
        itemsPerPage={5}
        pagination
        tableProps={{
          align: 'middle',
          hover: true,
          striped: true,
          responsive: true,
          bordered: true,
        }}
      />
    </>
  )
}

GlobalSmartTable.propTypes = {
  items: PropTypes.array,
  loading: PropTypes.bool,
  selectable: PropTypes.bool,
  handleSelectedItemsChange: PropTypes.func,
  setSelectedRows: PropTypes.func,
  scopedColumns: PropTypes.object,
  columns: PropTypes.array,
  customFilter: PropTypes.func,
}

And I'm using this Global CSmartTable in here

function handleSelectSchedules(rows, setSelectedSchedules) {
    const filterBlankItems = rows?.filter((el) => el?.status === 0)

    handleRowsSelectionStatus(rows, 'status')

    const returnIDs = filterBlankItems.map((item) => item.id)

    setSelectedSchedules(returnIDs)
  }
<GlobalSmartTable
            items={schedules}
            loading={loading}
            selectable={true}
            handleSelectedItemsChange={handleSelectSchedules}
            columns={columns}
            selectedRows={selectedSchedules}
            setSelectedRows={setSelectedSchedules}
            scopedColumns={{
              view: (item) => (
                <td>
                  <CButton
                    color="success"
                    style={{ color: 'white', borderRadius: '20px' }}
                    onClick={() => {
                      navigate(`/Schedule/ListSchedule/${item?.id}`)
                    }}
                  >
                    View
                  </CButton>
                </td>
              ),
              id: (item) => <td>{item.id}</td>,
              date: (item) => <td>{transformDate(item?.date)}</td>,
              hourStart: (item) => <td>{transformTime(item?.hourStart)}</td>,
              status: (item) => (
                <td>
                  <CTooltip content="Click to disapprove this Schedule">
                    <CButton
                      color=""
                      disabled={item.status === 0 ? true : false}
                      style={{ border: 'none' }}
                      onClick={() => {
                        updateScheduleStatus(item.id)
                      }}
                    >
                      <ClipLoader loading={loading} size={50} color={'#6F42C1'} />
                      {!loading && (
                        <CBadge color={getBadgeColor(item?.status)}>
                          {transformScheduleStatus(item?.status)}
                        </CBadge>
                      )}
                    </CButton>
                  </CTooltip>
                </td>
              ),
              employees: (item) => (
                <td>
                  {item?.scheduleWorkers?.length === 0 && 'Not Specified'}
                  {item?.scheduleWorkers?.map((workers) => {
                    return `${workers.firstName}, `
                  })}
                </td>
              ),
              job: (item) => (
                <td>
                  {item?.scheduleWorkers?.length === 0 && 'Not Specified'}
                  {item?.scheduleWorkers?.map((element, index, array) => {
                    if (element.job === array[index - 1]?.job) return ''
                    if (element?.job === '') return 'Not specified'
                    return `${element.job}, `
                  })}
                </td>
              ),
              memo: (item) => <td>{item?.memo ? item?.memo : '...'}</td>,
              receiptDate: (item) => <td>{transformDate(item?.receiptDate)}</td>,
              qboPoNumber: (item) => <td>{item?.qboPoNumber}</td>,
            }}
            customFilter={(customFilterColumns) => {
              const alteredColumns = customFilterColumns.map((column) => {
                if (column.key === 'date' || column.key === 'receiptDate') {
                  column = Object.assign(column, {
                    filter: (values, onChange) => { // Got this from Docs
                      const transformedValues = values?.map((value) => transformDate(value))
                      const unique = [...new Set(transformedValues)].sort()

                      return (
                        <>
                          <select
                            className="form-control"
                            onChange={(selected) => {
                              onChange((item) => {
                                if (transformDate(item) === selected.target.value) {
                                  return transformDate(item)
                                }
                              })
                            }}
                          >
                            {unique.map((date) => (
                              <>
                                <option label={date} value={date} key={date}>
                                  {transformDate(date)}
                                </option>
                              </>
                            ))}
                          </select>
                        </>
                      )
                    },
                  })
                }

                return column
              })

              return alteredColumns
            }}
          />

Here I receive all selected Rows and control if they would be selected or not

/**
 *
 * @param {array} rows
 * @param {string} field
 */

/** Stopped working after the upgrade, because the fields "_id" and "_selected" are not present anymore
*/
export function handleRowsSelectionStatus(rows, field) {
  return rows.map((row) => {
    row = Object.assign(row, { _selected: row[field] === 1 ? false : true })

    return row
  })
}

System

  • OS: Windows 10
  • Browser: Chrome 116

Conclusion

I'm missing something or it is a bug on the new upgrade packages?

Thanks in advance!

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions