Row and Column Reordering for DataTable
parent
2b302c7856
commit
c7e328a65b
|
@ -73,6 +73,18 @@ export default {
|
||||||
rowspan: {
|
rowspan: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: null
|
default: null
|
||||||
|
},
|
||||||
|
rowReorder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
,rowReorderIcon: {
|
||||||
|
type: String,
|
||||||
|
default: 'pi pi-bars'
|
||||||
|
},
|
||||||
|
reorderableColumn: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
</tr>
|
</tr>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<tr v-for="(row,i) of headerColumnGroup.rows" :key="i">
|
<tr v-for="(row,i) of headerColumnGroup.rows" :key="i">
|
||||||
<th v-for="(col,i) of row.columns" :key="col.columnKey||col.field||i" :style="col.headerStyle" :class="getColumnHeaderClass(col)" @click="onColumnHeaderClick($event, col)"
|
<th v-for="(col,i) of row.columns" :key="col.columnKey||col.field||i" :style="col.headerStyle" :class="getColumnHeaderClass(col)"
|
||||||
|
@dragstart="onColumnHeaderDragStart($event)" @dragover="onColumnHeaderDragOver($event)" @dragleave="onColumnHeaderDragLeave($event)" @drop="onColumnHeaderDrop($event)"
|
||||||
:colspan="col.colspan" :rowspan="col.rowspan">
|
:colspan="col.colspan" :rowspan="col.rowspan">
|
||||||
<ColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
|
<ColumnSlot :column="col" type="header" v-if="col.$scopedSlots.header" />
|
||||||
<span class="p-column-title" v-if="col.header">{{col.header}}</span>
|
<span class="p-column-title" v-if="col.header">{{col.header}}</span>
|
||||||
|
@ -51,13 +52,17 @@
|
||||||
<tbody class="p-datatable-tbody">
|
<tbody class="p-datatable-tbody">
|
||||||
<template v-if="!empty">
|
<template v-if="!empty">
|
||||||
<tr :class="getRowClass(rowData)" v-for="(rowData, index) of dataToRender" :key="getRowKey(rowData, index)"
|
<tr :class="getRowClass(rowData)" v-for="(rowData, index) of dataToRender" :key="getRowKey(rowData, index)"
|
||||||
@click="onRowClick($event, rowData, index)" @touchend="onRowTouchEnd($event)" @keydown="onRowKeyDown($event, rowData, index)" :tabindex="selectionMode ? '0' : null">
|
@click="onRowClick($event, rowData, index)" @touchend="onRowTouchEnd($event)" @keydown="onRowKeyDown($event, rowData, index)" :tabindex="selectionMode ? '0' : null"
|
||||||
|
@mousedown="onRowMouseDown($event)" @dragstart="onRowDragStart($event, index)" @dragover="onRowDragOver($event,index)" @dragleave="onRowDragLeave($event)" @dragend="onRowDragEnd($event)" @drop="onRowDrop($event)">
|
||||||
<td v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.bodyStyle" :class="col.bodyClass">
|
<td v-for="(col,i) of columns" :key="col.columnKey||col.field||i" :style="col.bodyStyle" :class="col.bodyClass">
|
||||||
<ColumnSlot :data="rowData" :column="col" type="body" v-if="col.$scopedSlots.body" />
|
<ColumnSlot :data="rowData" :column="col" type="body" v-if="col.$scopedSlots.body" />
|
||||||
<template v-else-if="col.selectionMode">
|
<template v-else-if="col.selectionMode">
|
||||||
<DTRadioButton :value="rowData" :checked="isSelected(rowData)" @change="toggleRowWithRadio" v-if="col.selectionMode === 'single'" />
|
<DTRadioButton :value="rowData" :checked="isSelected(rowData)" @change="toggleRowWithRadio" v-if="col.selectionMode === 'single'" />
|
||||||
<DTCheckbox :value="rowData" :checked="isSelected(rowData)" @change="toggleRowWithCheckbox" v-else-if="col.selectionMode ==='multiple'" />
|
<DTCheckbox :value="rowData" :checked="isSelected(rowData)" @change="toggleRowWithCheckbox" v-else-if="col.selectionMode ==='multiple'" />
|
||||||
</template>
|
</template>
|
||||||
|
<template v-else-if="col.rowReorder">
|
||||||
|
<i :class="['p-datatable-reorderablerow-handle', col.rowReorderIcon]"></i>
|
||||||
|
</template>
|
||||||
<template v-else>{{resolveFieldData(rowData, col.field)}}</template>
|
<template v-else>{{resolveFieldData(rowData, col.field)}}</template>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -294,6 +299,9 @@ export default {
|
||||||
colReorderIconWidth: null,
|
colReorderIconWidth: null,
|
||||||
colReorderIconHeight: null,
|
colReorderIconHeight: null,
|
||||||
draggedColumn: null,
|
draggedColumn: null,
|
||||||
|
draggedRowIndex: null,
|
||||||
|
droppedRowIndex: null,
|
||||||
|
rowDragging: null,
|
||||||
watch: {
|
watch: {
|
||||||
first(newValue) {
|
first(newValue) {
|
||||||
this.d_first = newValue;
|
this.d_first = newValue;
|
||||||
|
@ -980,8 +988,8 @@ export default {
|
||||||
this.documentColumnResizeEndListener = null;
|
this.documentColumnResizeEndListener = null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onColumnHeaderMouseDown(event) {
|
onColumnHeaderMouseDown(event, col) {
|
||||||
if (this.reorderableColumns) {
|
if (this.reorderableColumns && col.reorderableColumn) {
|
||||||
if (event.target.nodeName === 'INPUT' || event.target.nodeName === 'TEXTAREA' || DomHandler.hasClass(event.target, 'p-column-resizer'))
|
if (event.target.nodeName === 'INPUT' || event.target.nodeName === 'TEXTAREA' || DomHandler.hasClass(event.target, 'p-column-resizer'))
|
||||||
event.currentTarget.draggable = false;
|
event.currentTarget.draggable = false;
|
||||||
else
|
else
|
||||||
|
@ -1050,7 +1058,7 @@ export default {
|
||||||
if (allowDrop) {
|
if (allowDrop) {
|
||||||
ObjectUtils.reorderArray(this.columnOrder, dragIndex, dropIndex);
|
ObjectUtils.reorderArray(this.columnOrder, dragIndex, dropIndex);
|
||||||
|
|
||||||
this.$emit('colreorder', {
|
this.$emit('col-reorder', {
|
||||||
dragIndex: dragIndex,
|
dragIndex: dragIndex,
|
||||||
dropIndex: dropIndex,
|
dropIndex: dropIndex,
|
||||||
columns: this.columns
|
columns: this.columns
|
||||||
|
@ -1088,6 +1096,83 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
},
|
||||||
|
onRowMouseDown(event) {
|
||||||
|
if (DomHandler.hasClass(event.target, 'p-datatable-reorderablerow-handle'))
|
||||||
|
event.currentTarget.draggable = true;
|
||||||
|
else
|
||||||
|
event.currentTarget.draggable = false;
|
||||||
|
},
|
||||||
|
onRowDragStart(event, index) {
|
||||||
|
this.rowDragging = true;
|
||||||
|
this.draggedRowIndex = index;
|
||||||
|
event.dataTransfer.setData('text', 'b'); // For firefox
|
||||||
|
},
|
||||||
|
onRowDragOver(event, index) {
|
||||||
|
if (this.rowDragging && this.draggedRowIndex !== index) {
|
||||||
|
let rowElement = event.currentTarget;
|
||||||
|
let rowY = DomHandler.getOffset(rowElement).top + DomHandler.getWindowScrollTop();
|
||||||
|
let pageY = event.pageY;
|
||||||
|
let rowMidY = rowY + DomHandler.getOuterHeight(rowElement) / 2;
|
||||||
|
let prevRowElement = rowElement.previousElementSibling;
|
||||||
|
|
||||||
|
if (pageY < rowMidY) {
|
||||||
|
DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
|
||||||
|
this.droppedRowIndex = index;
|
||||||
|
if (prevRowElement)
|
||||||
|
DomHandler.addClass(prevRowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
else
|
||||||
|
DomHandler.addClass(rowElement, 'p-datatable-dragpoint-top');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (prevRowElement)
|
||||||
|
DomHandler.removeClass(prevRowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
else
|
||||||
|
DomHandler.addClass(rowElement, 'p-datatable-dragpoint-top');
|
||||||
|
|
||||||
|
this.droppedRowIndex = index + 1;
|
||||||
|
DomHandler.addClass(rowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRowDragLeave(event) {
|
||||||
|
let rowElement = event.currentTarget;
|
||||||
|
let prevRowElement = rowElement.previousElementSibling;
|
||||||
|
if (prevRowElement) {
|
||||||
|
DomHandler.removeClass(prevRowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
}
|
||||||
|
|
||||||
|
DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-bottom');
|
||||||
|
DomHandler.removeClass(rowElement, 'p-datatable-dragpoint-top');
|
||||||
|
},
|
||||||
|
onRowDragEnd(event) {
|
||||||
|
this.rowDragging = false;
|
||||||
|
this.draggedRowIndex = null;
|
||||||
|
this.droppedRowIndex = null;
|
||||||
|
event.currentTarget.draggable = false;
|
||||||
|
},
|
||||||
|
onRowDrop(event) {
|
||||||
|
let rowElement = event.currentTarget;
|
||||||
|
|
||||||
|
if (this.droppedRowIndex != null) {
|
||||||
|
let dropIndex = (this.draggedRowIndex > this.droppedRowIndex) ? this.droppedRowIndex : (this.droppedRowIndex === 0) ? 0 : this.droppedRowIndex - 1;
|
||||||
|
let processedData = [...this.processedData];
|
||||||
|
ObjectUtils.reorderArray(processedData, this.draggedRowIndex, dropIndex);
|
||||||
|
|
||||||
|
this.$emit('row-reorder', {
|
||||||
|
dragIndex: this.draggedRowIndex,
|
||||||
|
dropIndex: dropIndex,
|
||||||
|
value: processedData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup
|
||||||
|
this.onRowDragLeave(event);
|
||||||
|
this.onRowDragEnd(event);
|
||||||
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content-section implementation">
|
<div class="content-section implementation">
|
||||||
<DataTable :value="cars" :reorderableColumns="true" @colreorder="onColReorder">
|
<DataTable :value="cars" :reorderableColumns="true" @col-reorder="onColReorder" @row-reorder="onRowReorder">
|
||||||
|
<Column :rowReorder="true" headerStyle="width: 3em" :reorderableColumn="false" />
|
||||||
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"></Column>
|
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"></Column>
|
||||||
</DataTable>
|
</DataTable>
|
||||||
</div>
|
</div>
|
||||||
|
@ -20,12 +21,47 @@
|
||||||
<TabPanel header="Source">
|
<TabPanel header="Source">
|
||||||
<CodeHighlight>
|
<CodeHighlight>
|
||||||
<template v-pre>
|
<template v-pre>
|
||||||
|
<DataTable :value="cars" :reorderableColumns="true" @col-reorder="onColReorder" @row-reorder="onRowReorder">
|
||||||
|
<Column :rowReorder="true" headerStyle="width: 3em" :reorderableColumn="false" />
|
||||||
|
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"></Column>
|
||||||
|
</DataTable>
|
||||||
</template>
|
</template>
|
||||||
</CodeHighlight>
|
</CodeHighlight>
|
||||||
|
|
||||||
<CodeHighlight lang="javascript">
|
<CodeHighlight lang="javascript">
|
||||||
|
import CarService from '../../service/CarService';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
columns: null,
|
||||||
|
cars: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
carService: null,
|
||||||
|
created() {
|
||||||
|
this.carService = new CarService();
|
||||||
|
|
||||||
|
this.columns = [
|
||||||
|
{field: 'vin', header: 'Vin'},
|
||||||
|
{field: 'year', header: 'Year'},
|
||||||
|
{field: 'brand', header: 'Brand'},
|
||||||
|
{field: 'color', header: 'Color'}
|
||||||
|
];
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.carService.getCarsSmall().then(data => this.cars = data);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onColReorder(event) {
|
||||||
|
this.$toast.add({severity:'success', summary: 'Column Reordered', life: 3000});
|
||||||
|
},
|
||||||
|
onRowReorder(event) {
|
||||||
|
this.cars = event.value;
|
||||||
|
this.$toast.add({severity:'success', summary: 'Rows Reordered', life: 3000});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</CodeHighlight>
|
</CodeHighlight>
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</TabView>
|
</TabView>
|
||||||
|
@ -62,6 +98,10 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
onColReorder(event) {
|
onColReorder(event) {
|
||||||
this.$toast.add({severity:'success', summary: 'Column Reordered', life: 3000});
|
this.$toast.add({severity:'success', summary: 'Column Reordered', life: 3000});
|
||||||
|
},
|
||||||
|
onRowReorder(event) {
|
||||||
|
this.cars = event.value;
|
||||||
|
this.$toast.add({severity:'success', summary: 'Rows Reordered', life: 3000});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
Loading…
Reference in New Issue