Skip to content

Commit

Permalink
Fixed #1911 - Add sortableDisabled property to Column
Browse files Browse the repository at this point in the history
  • Loading branch information
mertsincan committed Mar 29, 2021
1 parent 9fca82f commit cca6f0f
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/components/column/Column.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ interface ColumnProps {
loadingBody?: any;
footer?: any;
sortable?: boolean;
sortableDisabled?: boolean;
filter?: boolean;
filterMatchMode?: string;
filterPlaceholder?: string;
Expand Down
4 changes: 3 additions & 1 deletion src/components/column/Column.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export class Column extends Component {
loadingBody: null,
footer: null,
sortable: false,
sortableDisabled: false,
sortFunction: null,
filter: false,
filterMatchMode: 'startsWith',
Expand Down Expand Up @@ -61,7 +62,8 @@ export class Column extends Component {
body: PropTypes.any,
loadingBody: PropTypes.func,
footer: PropTypes.any,
sortable: PropTypes.any,
sortable: PropTypes.bool,
sortableDisabled: PropTypes.bool,
sortFunction: PropTypes.func,
filter: PropTypes.bool,
filterMatchMode: PropTypes.string,
Expand Down
4 changes: 4 additions & 0 deletions src/components/datatable/DataTable.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
user-select: none;
}

.p-datatable .p-sortable-disabled {
cursor: auto;
}

.p-datatable .p-sortable-column .p-column-title,
.p-datatable .p-sortable-column .p-sortable-column-icon,
.p-datatable .p-sortable-column .p-sortable-column-badge {
Expand Down
11 changes: 6 additions & 5 deletions src/components/datatable/DataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ export class DataTable extends Component {

if (this.props.sortMode === 'multiple') {
let metaKey = event.originalEvent.metaKey || event.originalEvent.ctrlKey;
let sortableDisabledFields = event.sortableDisabledFields;
multiSortMeta = this.getMultiSortMeta();

if (multiSortMeta && multiSortMeta instanceof Array) {
Expand All @@ -562,7 +563,7 @@ export class DataTable extends Component {

if (sortOrder) {
if(!multiSortMeta || !metaKey) {
multiSortMeta = [];
multiSortMeta = multiSortMeta ? multiSortMeta.filter((meta) => sortableDisabledFields.some((field) => field === meta.field)) : [];
}

this.addSortMeta(newMetaData, multiSortMeta);
Expand All @@ -572,7 +573,7 @@ export class DataTable extends Component {
}

eventMeta = {
multiSortMeta: multiSortMeta
multiSortMeta
};
}
else {
Expand All @@ -582,8 +583,8 @@ export class DataTable extends Component {
}

eventMeta = {
sortField: sortField,
sortOrder: sortOrder
sortField,
sortOrder
};
}

Expand Down Expand Up @@ -1317,7 +1318,7 @@ export class DataTable extends Component {
}

createTableHeader(value, columns, columnGroup) {
return <TableHeader value={value} onSort={this.onSort} sortField={this.getSortField()} sortOrder={this.getSortOrder()} multiSortMeta={this.getMultiSortMeta()} columnGroup={columnGroup}
return <TableHeader value={value} sortMode={this.props.sortMode} onSort={this.onSort} sortField={this.getSortField()} sortOrder={this.getSortOrder()} multiSortMeta={this.getMultiSortMeta()} columnGroup={columnGroup}
resizableColumns={this.props.resizableColumns} onColumnResizeStart={this.onColumnResizeStart} onFilter={this.onFilter} filterDelay={this.props.filterDelay}
onHeaderCheckboxClick={this.onHeaderCheckboxClick} headerCheckboxSelected={this.isAllSelected()}
reorderableColumns={this.props.reorderableColumns} onColumnDragStart={this.onColumnDragStart} filters={this.getFilters()}
Expand Down
40 changes: 31 additions & 9 deletions src/components/datatable/HeaderCell.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,17 @@ export class HeaderCell extends Component {
}

onClick(event) {
if (this.props.columnProps.sortable) {
const { field, sortField, sortable, sortFunction } = this.props.columnProps;
if (!this.isSortableDisabled()) {
let targetNode = event.target;
if(DomHandler.hasClass(targetNode, 'p-sortable-column') || DomHandler.hasClass(targetNode, 'p-column-title')
if (DomHandler.hasClass(targetNode, 'p-sortable-column') || DomHandler.hasClass(targetNode, 'p-column-title')
|| DomHandler.hasClass(targetNode, 'p-sortable-column-icon') || DomHandler.hasClass(targetNode.parentElement, 'p-sortable-column-icon')) {
this.props.onSort({
originalEvent: event,
sortField: this.props.columnProps.sortField || this.props.columnProps.field,
sortFunction: this.props.columnProps.sortFunction,
sortable: this.props.columnProps.sortable
sortField: sortField || field,
sortFunction,
sortable,
sortableDisabledFields: this.props.sortableDisabledFields
});

DomHandler.clearSelection();
Expand Down Expand Up @@ -106,12 +108,21 @@ export class HeaderCell extends Component {
}
}

componentDidUpdate(prevProps) {
const prevColumnProps = prevProps.columnProps;
const columnProps = this.props.columnProps;

if (prevColumnProps.sortableDisabled !== columnProps.sortableDisabled || prevColumnProps.sortable !== columnProps.sortable) {
this.props.onSortableChange();
}
}

getAriaSort(sorted, sortOrder) {
if (this.props.columnProps.sortable) {
let sortIcon = sorted ? sortOrder < 0 ? 'pi-sort-amount-down' : 'pi-sort-amount-up-alt': 'pi-sort-alt';
if (sortIcon === 'pi-sort-down')
if (sortIcon === 'pi-sort-amount-down')
return 'descending';
else if (sortIcon === 'pi-sort-up')
else if (sortIcon === 'pi-sort-amount-up-alt')
return 'ascending';
else
return 'none';
Expand All @@ -121,6 +132,14 @@ export class HeaderCell extends Component {
}
}

isSortableDisabled() {
return this.props.columnProps.sortable && (this.props.allSortableDisabled || this.props.columnProps.sortableDisabled);
}

isSingleSorted() {
return this.props.sortField !== null ? (this.props.columnProps.field === this.props.sortField || this.props.columnProps.sortField === this.props.sortField) : false;
}

renderSortIcon(sorted, sortOrder) {
if (this.props.columnProps.sortable) {
let sortIcon = sorted ? sortOrder < 0 ? 'pi-sort-amount-down' : 'pi-sort-amount-up-alt': 'pi-sort-alt';
Expand Down Expand Up @@ -167,7 +186,7 @@ export class HeaderCell extends Component {
else {
let sortMetaDataIndex = this.getMultiSortMetaDataIndex();
let multiSortMetaData = sortMetaDataIndex !== -1 ? this.props.multiSortMeta[sortMetaDataIndex] : null;
let singleSorted = this.props.sortField !== null ? (this.props.columnProps.field === this.props.sortField || this.props.columnProps.sortField === this.props.sortField) : false;
let singleSorted = this.isSingleSorted();
let multipleSorted = multiSortMetaData !== null;
let sortOrder = 0;
let resizer = this.props.resizableColumns && <span className="p-column-resizer p-clickable" onMouseDown={this.onResizerMouseDown}></span>;
Expand All @@ -178,17 +197,20 @@ export class HeaderCell extends Component {
sortOrder = multiSortMetaData.order;

let sorted = this.props.columnProps.sortable && (singleSorted || multipleSorted);
let isSortableDisabled = this.isSortableDisabled();
let className = classNames({'p-sortable-column': this.props.columnProps.sortable,
'p-highlight': sorted,
'p-sortable-disabled': isSortableDisabled,
'p-resizable-column': this.props.resizableColumns,
'p-selection-column': this.props.columnProps.selectionMode}, this.props.columnProps.headerClassName||this.props.columnProps.className);

let sortIconElement = this.renderSortIcon(sorted, sortOrder);
let ariaSortData = this.getAriaSort(sorted, sortOrder);
let sortBadge = this.renderSortBadge(sortMetaDataIndex);
let tabIndex = !isSortableDisabled ? this.props.tabIndex : null

return (
<th ref={(el) => this.el = el} role="columnheader" tabIndex={this.props.columnProps.sortable ? this.props.tabIndex : null}
<th ref={(el) => this.el = el} role="columnheader" tabIndex={tabIndex}
className={className} style={this.props.columnProps.headerStyle||this.props.columnProps.style} onClick={this.onClick} onMouseDown={this.onMouseDown} onKeyDown={this.onKeyDown}
colSpan={this.props.columnProps.colSpan} rowSpan={this.props.columnProps.rowSpan} aria-sort={ariaSortData}
onDragStart={this.props.onDragStart} onDragOver={this.props.onDragOver} onDragLeave={this.props.onDragLeave} onDrop={this.props.onDrop}>
Expand Down
60 changes: 58 additions & 2 deletions src/components/datatable/TableHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,21 @@ import {HeaderCell} from './HeaderCell';

export class TableHeader extends Component {

constructor(props) {
super(props);

this.state = {
sortableDisabledFields: [],
allSortableDisabled: false
}

this.onSortableChange = this.onSortableChange.bind(this);
}

createHeaderCells(columns, renderOptions) {
return React.Children.map(columns, (column, i) => {
return <HeaderCell key={column.columnKey||column.field||i} columnProps={column.props} value={this.props.value} onSort={this.props.onSort}
sortField={this.props.sortField} sortOrder={this.props.sortOrder} multiSortMeta={this.props.multiSortMeta}
return <HeaderCell key={column.props.columnKey||column.props.field||i} allSortableDisabled={this.isAllSortableDisabled()} onSortableChange={this.onSortableChange} columnProps={column.props} value={this.props.value} onSort={this.props.onSort}
sortableDisabledFields={this.state.sortableDisabledFields} sortMode={this.props.sortMode} sortField={this.props.sortField} sortOrder={this.props.sortOrder} multiSortMeta={this.props.multiSortMeta}
resizableColumns={this.props.resizableColumns} onColumnResizeStart={this.props.onColumnResizeStart} filterDelay={this.props.filterDelay}
onFilter={this.props.onFilter} renderOptions={renderOptions} onHeaderCheckboxClick={this.props.onHeaderCheckboxClick} headerCheckboxSelected={this.props.headerCheckboxSelected}
reorderableColumns={this.props.reorderableColumns} onDragStart={this.props.onColumnDragStart} onDragOver={this.props.onColumnDragOver}
Expand All @@ -26,6 +37,51 @@ export class TableHeader extends Component {
return false;
}

isSingleSort() {
return this.props.sortMode === 'single';
}

isMultipleSort() {
return this.props.sortMode === 'multiple';
}

isAllSortableDisabled() {
return this.isSingleSort() && this.state.allSortableDisabled;
}

isColumnSorted(column) {
return this.props.sortField !== null ? (column.props.field === this.props.sortField || column.props.sortField === this.props.sortField) : false;
}

updateSortableDisabled() {
if (this.isSingleSort() || (this.isMultipleSort() && this.props.onSort)) {
let sortableDisabledFields = [];
let allSortableDisabled = false;
React.Children.forEach(this.props.children, (column) => {
if (column.props.sortableDisabled) {
sortableDisabledFields.push(column.props.sortField || column.props.field);

if (!allSortableDisabled && this.isColumnSorted(column)) {
allSortableDisabled = true;
}
}
});

this.setState({
sortableDisabledFields,
allSortableDisabled
});
}
}

onSortableChange() {
this.updateSortableDisabled();
}

componentDidMount() {
this.updateSortableDisabled();
}

render() {
let content;
if (this.props.columnGroup) {
Expand Down

0 comments on commit cca6f0f

Please sign in to comment.