Skip to content

Commit

Permalink
Fixed #1303 - Add isDataSelectable property to DataTable
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Jan 15, 2022
1 parent 2ac302f commit 308b069
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 49 deletions.
66 changes: 44 additions & 22 deletions components/lib/datatable/BodyCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class BodyCell extends Component {
this.onBlur = this.onBlur.bind(this);
this.onEditorFocus = this.onEditorFocus.bind(this);
this.onRowToggle = this.onRowToggle.bind(this);
this.onRadioChange = this.onRadioChange.bind(this);
this.onCheckboxChange = this.onCheckboxChange.bind(this);

this.onRowEditSave = this.onRowEditSave.bind(this);
this.onRowEditCancel = this.onRowEditCancel.bind(this);
Expand Down Expand Up @@ -69,9 +71,8 @@ export class BodyCell extends Component {
return this.getColumnProp('frozen') ? Object.assign({}, columnStyle, bodyStyle, this.state.styleObject) : Object.assign({}, columnStyle, bodyStyle);
}

getCellCallbackParams(event) {
getCellParams() {
return {
originalEvent: event,
value: this.resolveFieldData(),
field: this.field,
rowData: this.props.rowData,
Expand All @@ -83,6 +84,14 @@ export class BodyCell extends Component {
}
}

getCellCallbackParams(event) {
const params = this.getCellParams();
return {
originalEvent: event,
...params
}
}

resolveFieldData(data) {
return ObjectUtils.resolveFieldData(data || this.props.rowData, this.field);
}
Expand Down Expand Up @@ -153,28 +162,27 @@ export class BodyCell extends Component {
findNextSelectableCell(cell) {
let nextCell = cell.nextElementSibling;

return nextCell ? (DomHandler.hasClass(nextCell, 'p-selectable-cell') ? nextCell : this.findNextSelectableRow(nextCell)) : null;
return nextCell ? (DomHandler.hasClass(nextCell, 'p-selectable-cell') ? nextCell : this.findNextSelectableCell(nextCell)) : null;
}

findPrevSelectableCell(cell) {
let prevCell = cell.previousElementSibling;

return prevCell ? (DomHandler.hasClass(prevCell, 'p-selectable-cell') ? prevCell : this.findPrevSelectableRow(prevCell)) : null;
return prevCell ? (DomHandler.hasClass(prevCell, 'p-selectable-cell') ? prevCell : this.findPrevSelectableCell(prevCell)) : null;
}

findNextSelectableRow(row) {
let nextRow = row.nextElementSibling;
findDownSelectableCell(cell) {
let downRow = cell.parentElement.nextElementSibling;
let downCell = downRow ? downRow.children[this.props.index] : null;

return nextRow ? (DomHandler.hasClass(nextRow, 'p-selectable-row') ? nextRow : this.findNextSelectableRow(nextRow)) : null;
return downRow && downCell ? (DomHandler.hasClass(downRow, 'p-selectable-row') && DomHandler.hasClass(downCell, 'p-selectable-cell') ? downCell : this.findDownSelectableCell(downCell)) : null;
}

findPrevSelectableRow(row) {
let prevRow = row.previousElementSibling;
if (prevRow) {
return DomHandler.hasClass(prevRow, 'p-selectable-row') ? prevRow : this.findPrevSelectableRow(prevRow);
}
findUpSelectableCell(cell) {
let upRow = cell.parentElement.previousElementSibling;
let upCell = upRow ? upRow.children[this.props.index] : null;

return null;
return upRow && upCell ? (DomHandler.hasClass(upRow, 'p-selectable-row') && DomHandler.hasClass(upCell, 'p-selectable-cell') ? upCell : this.findUpSelectableCell(upCell)) : null;
}

changeTabIndex(currentCell, nextCell) {
Expand Down Expand Up @@ -330,9 +338,8 @@ export class BodyCell extends Component {

//up arrow
case 38:
let prevRow = this.findPrevSelectableRow(cell.parentElement);
if (prevRow) {
let upCell = prevRow.children[this.props.index];
let upCell = this.findUpSelectableCell(cell);
if (upCell) {
this.changeTabIndex(cell, upCell);
upCell.focus();
}
Expand All @@ -342,9 +349,8 @@ export class BodyCell extends Component {

//down arrow
case 40:
let nextRow = this.findNextSelectableRow(cell.parentElement);
if (nextRow) {
let downCell = nextRow.children[this.props.index];
let downCell = this.findDownSelectableCell(cell);
if (downCell) {
this.changeTabIndex(cell, downCell);
downCell.focus();
}
Expand Down Expand Up @@ -387,6 +393,22 @@ export class BodyCell extends Component {
this.onClick(event);
}

onRadioChange(event) {
this.props.onRadioChange({
originalEvent: event,
data: this.props.rowData,
index: this.props.rowIndex
});
}

onCheckboxChange(event) {
this.props.onCheckboxChange({
originalEvent: event,
data: this.props.rowData,
index: this.props.rowIndex
});
}

onRowToggle(event) {
this.props.onRowToggle({
originalEvent: event,
Expand Down Expand Up @@ -516,7 +538,7 @@ export class BodyCell extends Component {
'p-editable-column': editor,
'p-cell-editing': editor && this.state.editing,
'p-frozen-column': frozen,
'p-selectable-cell': this.props.allowCellSelection,
'p-selectable-cell': this.props.allowCellSelection && this.props.isSelectable({ data: this.getCellParams(), index: this.props.rowIndex }),
'p-highlight': cellSelected,
[`p-align-${align}`]: !!align
});
Expand All @@ -528,8 +550,8 @@ export class BodyCell extends Component {

content = showSelection && (
<>
{selectionMode === 'single' && <RowRadioButton value={this.props.rowData} checked={this.props.selected} onChange={this.props.onRadioChange} tabIndex={this.props.tabIndex} tableSelector={this.props.tableSelector} />}
{selectionMode === 'multiple' && <RowCheckbox value={this.props.rowData} checked={this.props.selected} onChange={this.props.onCheckboxChange} tabIndex={this.props.tabIndex} />}
{selectionMode === 'single' && <RowRadioButton checked={this.props.selected} onChange={this.onRadioChange} tabIndex={this.props.tabIndex} tableSelector={this.props.tableSelector} />}
{selectionMode === 'multiple' && <RowCheckbox checked={this.props.selected} onChange={this.onCheckboxChange} tabIndex={this.props.tabIndex} />}
</>
)
}
Expand Down
8 changes: 2 additions & 6 deletions components/lib/datatable/BodyRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,6 @@ export class BodyRow extends Component {
}

onClick(event) {
const row = event.currentTarget;
const tabbableEl = DomHandler.findSingle(row.parentElement, 'tr[tabIndex="0"]');
tabbableEl && this.changeTabIndex(tabbableEl, row);

this.props.onRowClick({ originalEvent: event, data: this.props.rowData, index: this.props.index });
}

Expand Down Expand Up @@ -328,7 +324,7 @@ export class BodyRow extends Component {
editing={editing} editingMeta={this.props.editingMeta} editMode={this.props.editMode} onRowEditInit={this.onEditInit} onRowEditSave={this.onEditSave} onRowEditCancel={this.onEditCancel} onEditingMetaChange={this.props.onEditingMetaChange}
onRowToggle={this.props.onRowToggle} selection={this.props.selection} allowCellSelection={this.props.allowCellSelection} compareSelectionBy={this.props.compareSelectionBy} selectOnEdit={this.props.selectOnEdit} selected={this.props.selected}
onClick={this.props.onCellClick} onMouseDown={this.props.onCellMouseDown} onMouseUp={this.props.onCellMouseUp} tabIndex={this.props.tabIndex}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} frozenRow={this.props.frozenRow}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} frozenRow={this.props.frozenRow} isSelectable={this.props.isSelectable}
showSelectionElement={this.props.showSelectionElement} showRowReorderElement={this.props.showRowReorderElement} onRadioChange={this.props.onRadioChange} onCheckboxChange={this.props.onCheckboxChange}
expanded={this.props.expanded} expandedRowIcon={this.props.expandedRowIcon} collapsedRowIcon={this.props.collapsedRowIcon}
virtualScrollerOptions={this.props.virtualScrollerOptions} />
Expand All @@ -344,7 +340,7 @@ export class BodyRow extends Component {
const className = classNames(rowClassName, {
'p-highlight': !this.props.allowCellSelection && this.props.selected,
'p-highlight-contextmenu': this.props.contextMenuSelected,
'p-selectable-row': this.props.allowRowSelection,
'p-selectable-row': this.props.allowRowSelection && this.props.isSelectable({ data: this.props.rowData, index: this.props.index }),
'p-row-odd': this.props.index % 2 !== 0
});
const content = this.renderContent();
Expand Down
3 changes: 2 additions & 1 deletion components/lib/datatable/DataTable.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
table-layout: auto;
}

.p-datatable-hoverable-rows .p-selectable-row {
.p-datatable-selectable .p-selectable-row,
.p-datatable-selectable-cell .p-selectable-cell {
cursor: pointer;
}

Expand Down
6 changes: 6 additions & 0 deletions components/lib/datatable/DataTable.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ interface DataTablePFSEvent extends DataTablePageParams, DataTableSortParams, Da
[key: string]: any;
}

interface DataTableDataSelectableParams {
data: any;
index: number;
}

interface DataTableSelectionChangeParams {
originalEvent: React.SyntheticEvent;
value: any;
Expand Down Expand Up @@ -316,6 +321,7 @@ export interface DataTableProps {
onRowEditComplete?(e: DataTableRowEditCompleteParams): void;
showSelectionElement?(data: any, options: DataTableShowSelectionElementOptions): boolean | undefined | null;
showRowReorderElement?(data: any, options: DataTableShowRowReorderElementOptions): boolean | undefined | null;
isDataSelectable?(e: DataTableDataSelectableParams): boolean | undefined | null;
onSelectionChange?(e: DataTableSelectionChangeParams): void;
onContextMenuSelectionChange?(e: DataTableSelectionChangeParams): void;
rowExpansionTemplate?(data: any, options: DataTableRowExpansionTemplate): React.ReactNode;
Expand Down
32 changes: 27 additions & 5 deletions components/lib/datatable/DataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export class DataTable extends Component {
globalFilterFields: null,
showSelectionElement: null,
showRowReorderElement: null,
isDataSelectable: null,
onColumnResizeEnd: null,
onColumnResizerClick: null,
onColumnResizerDoubleClick: null,
Expand Down Expand Up @@ -233,6 +234,7 @@ export class DataTable extends Component {
onRowEditComplete: PropTypes.func,
showSelectionElement: PropTypes.func,
showRowReorderElement: PropTypes.func,
isDataSelectable: PropTypes.func,
onColumnResizeEnd: PropTypes.func,
onColumnResizerClick: PropTypes.func,
onColumnResizerDoubleClick: PropTypes.func,
Expand Down Expand Up @@ -646,14 +648,31 @@ export class DataTable extends Component {
return this.props.sortMode === 'single' ? this.props.sortField : (this.state.groupRowsSortMeta ? this.state.groupRowsSortMeta.field : null);
}

getSelectableData(val) {
if (this.props.showSelectionElement || this.props.isDataSelectable) {
return val.filter((data, index) => {
let isSelectable = true;

if (this.props.showSelectionElement)
isSelectable = this.props.showSelectionElement({ rowIndex: index, props: this.props });
if (this.props.isDataSelectable && isSelectable)
isSelectable = this.props.isDataSelectable({ data, index });

return isSelectable;
});
}

return val;
}

allRowsSelected(processedData) {
if (this.props.onSelectAllChange) {
return this.props.selectAll;
}
else {
const data = this.props.selectionPageOnly ? this.dataToRender(processedData) : processedData;
const val = this.props.frozenValue ? [...this.props.frozenValue, ...data] : data;
const selectableVal = this.props.showSelectionElement ? val.filter((data, index) => this.props.showSelectionElement(data, { rowIndex: index, props: this.props })) : val;
const selectableVal = this.getSelectableData(val);

return selectableVal && this.props.selection && selectableVal.every(sv => this.props.selection.some(s => this.isEquals(s, sv)));
}
Expand Down Expand Up @@ -844,7 +863,7 @@ export class DataTable extends Component {

if (checked) {
selection = this.props.frozenValue ? [...selection, ...this.props.frozenValue, ...data] : [...selection, ...data];
selection = this.props.showSelectionElement ? selection.filter((data, index) => this.props.showSelectionElement(data, { rowIndex: index, props: this.props })) : selection;
selection = this.getSelectableData(selection);

this.props.onAllRowsSelect && this.props.onAllRowsSelect({ originalEvent, data: selection, type: 'all' });
}
Expand Down Expand Up @@ -1640,7 +1659,7 @@ export class DataTable extends Component {
rowGroupHeaderTemplate={this.props.rowGroupHeaderTemplate} rowExpansionTemplate={this.props.rowExpansionTemplate} rowGroupFooterTemplate={this.props.rowGroupFooterTemplate}
onRowEditChange={this.props.onRowEditChange} compareSelectionBy={this.props.compareSelectionBy} selectOnEdit={this.props.selectOnEdit}
onRowEditInit={this.props.onRowEditInit} rowEditValidator={this.props.rowEditValidator} onRowEditSave={this.props.onRowEditSave} onRowEditComplete={this.props.onRowEditComplete} onRowEditCancel={this.props.onRowEditCancel}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} selectionAutoFocus={this.props.selectionAutoFocus}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} selectionAutoFocus={this.props.selectionAutoFocus} isDataSelectable={this.props.isDataSelectable}
showSelectionElement={this.props.showSelectionElement} showRowReorderElement={this.props.showRowReorderElement}
expandedRowIcon={this.props.expandedRowIcon} collapsedRowIcon={this.props.collapsedRowIcon} rowClassName={this.props.rowClassName}
isVirtualScrollerDisabled={true} />
Expand All @@ -1660,7 +1679,7 @@ export class DataTable extends Component {
rowGroupHeaderTemplate={this.props.rowGroupHeaderTemplate} rowExpansionTemplate={this.props.rowExpansionTemplate} rowGroupFooterTemplate={this.props.rowGroupFooterTemplate}
onRowEditChange={this.props.onRowEditChange} compareSelectionBy={this.props.compareSelectionBy} selectOnEdit={this.props.selectOnEdit}
onRowEditInit={this.props.onRowEditInit} rowEditValidator={this.props.rowEditValidator} onRowEditSave={this.props.onRowEditSave} onRowEditComplete={this.props.onRowEditComplete} onRowEditCancel={this.props.onRowEditCancel}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} selectionAutoFocus={this.props.selectionAutoFocus}
cellClassName={this.props.cellClassName} responsiveLayout={this.props.responsiveLayout} selectionAutoFocus={this.props.selectionAutoFocus} isDataSelectable={this.props.isDataSelectable}
showSelectionElement={this.props.showSelectionElement} showRowReorderElement={this.props.showRowReorderElement}
expandedRowIcon={this.props.expandedRowIcon} collapsedRowIcon={this.props.collapsedRowIcon} rowClassName={this.props.rowClassName}
virtualScrollerContentRef={contentRef} virtualScrollerOptions={options} isVirtualScrollerDisabled={isVirtualScrollerDisabled} />
Expand Down Expand Up @@ -1778,8 +1797,11 @@ export class DataTable extends Component {
const totalRecords = this.getTotalRecords(processedData);
const empty = ObjectUtils.isEmpty(processedData);
const selectionModeInColumn = this.getSelectionModeInColumn(columns);
const selectable = this.props.selectionMode || selectionModeInColumn;
const className = classNames('p-datatable p-component', {
'p-datatable-hoverable-rows': this.props.rowHover || this.props.selectionMode || selectionModeInColumn,
'p-datatable-hoverable-rows': this.props.rowHover,
'p-datatable-selectable': selectable && !this.props.cellSelection,
'p-datatable-selectable-cell': selectable && this.props.cellSelection,
'p-datatable-auto-layout': this.props.autoLayout,
'p-datatable-resizable': this.props.resizableColumns,
'p-datatable-resizable-fit': this.props.resizableColumns && this.props.columnResizeMode === 'fit',
Expand Down
5 changes: 1 addition & 4 deletions components/lib/datatable/RowCheckbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ export class RowCheckbox extends Component {
if (!this.props.disabled) {
this.setState({ focused: true });

this.props.onChange({
originalEvent: event,
data: this.props.value
});
this.props.onChange(event);
}
}

Expand Down
5 changes: 1 addition & 4 deletions components/lib/datatable/RowRadioButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ export class RowRadioButton extends Component {

onClick(event) {
if (!this.props.disabled) {
this.props.onChange({
originalEvent: event,
data: this.props.value
});
this.props.onChange(event);

this.input.focus();
}
Expand Down
Loading

0 comments on commit 308b069

Please sign in to comment.