Fixed #1841 - DataTable component does not work correctly "Checkbox selection" together with "lazy"
parent
e08fd2d1d0
commit
229ba94153
|
@ -82,7 +82,7 @@ import TableFooter from './TableFooter.vue';
|
|||
export default {
|
||||
name: 'DataTable',
|
||||
emits: ['value-change', 'update:first', 'update:rows', 'page', 'update:sortField', 'update:sortOrder', 'update:multiSortMeta', 'sort', 'filter', 'row-click', 'row-dblclick',
|
||||
'update:selection', 'row-select', 'row-unselect', 'update:contextMenuSelection', 'row-contextmenu', 'row-unselect-all', 'row-select-all',
|
||||
'update:selection', 'row-select', 'row-unselect', 'update:contextMenuSelection', 'row-contextmenu', 'row-unselect-all', 'row-select-all', 'select-all-change',
|
||||
'column-resize-end', 'column-reorder', 'row-reorder', 'update:expandedRows', 'row-collapse', 'row-expand',
|
||||
'update:expandedRowGroups', 'rowgroup-collapse', 'rowgroup-expand', 'update:filters', 'state-restore', 'state-save',
|
||||
'cell-edit-init', 'cell-edit-complete', 'cell-edit-cancel', 'update:editingRows', 'row-edit-init', 'row-edit-save', 'row-edit-cancel'],
|
||||
|
@ -211,6 +211,10 @@ export default {
|
|||
type: Object,
|
||||
default: null
|
||||
},
|
||||
selectAll: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
rowHover: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
@ -883,15 +887,24 @@ export default {
|
|||
}
|
||||
},
|
||||
toggleRowsWithCheckbox(event) {
|
||||
const processedData = this.processedData;
|
||||
const checked = this.allRowsSelected;
|
||||
const _selection = checked ? [] : (this.frozenValue ? [...this.frozenValue, ...processedData]: processedData);
|
||||
if (this.selectAll !== null) {
|
||||
this.$emit('select-all-change', event);
|
||||
}
|
||||
else {
|
||||
const { originalEvent, checked } = event;
|
||||
let _selection = [];
|
||||
|
||||
if (checked) {
|
||||
_selection = this.frozenValue ? [...this.frozenValue, ...this.processedData] : this.processedData;
|
||||
this.$emit('row-select-all', {originalEvent, data: _selection});
|
||||
}
|
||||
else {
|
||||
this.$emit('row-unselect-all', {originalEvent});
|
||||
}
|
||||
|
||||
this.$emit('update:selection', _selection);
|
||||
|
||||
if (checked)
|
||||
this.$emit('row-unselect-all', {originalEvent: event});
|
||||
else
|
||||
this.$emit('row-select-all', {originalEvent: event, data: _selection});
|
||||
}
|
||||
},
|
||||
isSingleSelectionMode() {
|
||||
return this.selectionMode === 'single';
|
||||
|
@ -1887,9 +1900,13 @@ export default {
|
|||
return ['p-datatable-loading-icon pi-spin', this.loadingIcon];
|
||||
},
|
||||
allRowsSelected() {
|
||||
const val = this.frozenValue ? [...this.frozenValue, ...this.processedData]: this.processedData;
|
||||
const length = this.lazy ? this.totalRecords : (val ? val.length : 0);
|
||||
return (val && length > 0 && this.selection && this.selection.length > 0 && this.selection.length === length);
|
||||
if (this.selectAll !== null) {
|
||||
return this.selectAll;
|
||||
}
|
||||
else {
|
||||
const val = this.frozenValue ? [...this.frozenValue, ...this.processedData] : this.processedData;
|
||||
return val && this.selection && Array.isArray(this.selection) && val.every(v => this.selection.some(s => this.equals(s, v)));
|
||||
}
|
||||
},
|
||||
attributeSelector() {
|
||||
return UniqueComponentId();
|
||||
|
|
|
@ -24,7 +24,10 @@ export default {
|
|||
onClick(event) {
|
||||
if (!this.$attrs.disabled) {
|
||||
this.focused = true;
|
||||
this.$emit('change', event);
|
||||
this.$emit('change', {
|
||||
originalEvent: event,
|
||||
checked: !this.checked
|
||||
});
|
||||
}
|
||||
},
|
||||
onFocus() {
|
||||
|
|
|
@ -21,7 +21,7 @@ export default class CustomerService {
|
|||
}
|
||||
|
||||
getCustomers(params) {
|
||||
const queryParams = Object.keys(params).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])).join('&');
|
||||
const queryParams = params ? Object.keys(params).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k])).join('&') : '';
|
||||
return fetch('https://www.primefaces.org/data/customers?' + queryParams).then(res => res.json())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
|
||||
<div class="content-section implementation">
|
||||
<div class="card">
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt"
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt" dataKey="id"
|
||||
:totalRecords="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)" @filter="onFilter($event)" filterDisplay="row"
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll" >
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll"
|
||||
v-model:selection="selectedCustomers" :selectAll="selectAll" @select-all-change="onSelectAllChange" @row-select="onRowSelect" @row-unselect="onRowUnselect">
|
||||
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
|
||||
<Column field="name" header="Name" filterMatchMode="startsWith" ref="name" :sortable="true">
|
||||
<template #filter="{filterModel,filterCallback}">
|
||||
<InputText type="text" v-model="filterModel.value" @keydown.enter="filterCallback()" class="p-column-filter" placeholder="Search by name"/>
|
||||
|
@ -53,6 +55,8 @@ export default {
|
|||
loading: false,
|
||||
totalRecords: 0,
|
||||
customers: null,
|
||||
selectedCustomers: null,
|
||||
selectAll: false,
|
||||
filters: {
|
||||
'name': {value: '', matchMode: 'contains'},
|
||||
'country.name': {value: '', matchMode: 'contains'},
|
||||
|
@ -72,9 +76,11 @@ export default {
|
|||
content: `
|
||||
<template>
|
||||
<div>
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt"
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt" dataKey="id"
|
||||
:totalRecords="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)" @filter="onFilter($event)" filterDisplay="row"
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll">
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll"
|
||||
v-model:selection="selectedCustomers" :selectAll="selectAll" @select-all-change="onSelectAllChange" @row-select="onRowSelect" @row-unselect="onRowUnselect">
|
||||
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
|
||||
<Column field="name" header="Name" filterMatchMode="startsWith" ref="name" :sortable="true">
|
||||
<template #filter="{filterModel,filterCallback}">
|
||||
<InputText type="text" v-model="filterModel.value" @keydown.enter="filterCallback()" class="p-column-filter" placeholder="Search by name"/>
|
||||
|
@ -108,6 +114,8 @@ export default {
|
|||
loading: false,
|
||||
totalRecords: 0,
|
||||
customers: null,
|
||||
selectedCustomers: null,
|
||||
selectAll: false,
|
||||
filters: {
|
||||
'name': {value: '', matchMode: 'contains'},
|
||||
'country.name': {value: '', matchMode: 'contains'},
|
||||
|
@ -166,6 +174,26 @@ export default {
|
|||
onFilter() {
|
||||
this.lazyParams.filters = this.filters;
|
||||
this.loadLazyData();
|
||||
},
|
||||
onSelectAllChange(event) {
|
||||
const selectAll = event.checked;
|
||||
|
||||
if (selectAll) {
|
||||
this.customerService.getCustomers().then(data => {
|
||||
this.selectAll = true;
|
||||
this.selectedCustomers = data.customers;
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.selectAll = false;
|
||||
this.selectedCustomers = [];
|
||||
}
|
||||
},
|
||||
onRowSelect() {
|
||||
this.selectAll = this.selectedCustomers.length === this.totalRecords
|
||||
},
|
||||
onRowUnselect() {
|
||||
this.selectAll = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -177,9 +205,11 @@ export default {
|
|||
content: `
|
||||
<template>
|
||||
<div>
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt"
|
||||
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt" dataKey="id"
|
||||
:totalRecords="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)" @filter="onFilter($event)" filterDisplay="row"
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll">
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll"
|
||||
v-model:selection="selectedCustomers" :selectAll="selectAll" @select-all-change="onSelectAllChange" @row-select="onRowSelect" @row-unselect="onRowUnselect">
|
||||
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
|
||||
<Column field="name" header="Name" filterMatchMode="startsWith" ref="name" :sortable="true">
|
||||
<template #filter="{filterModel,filterCallback}">
|
||||
<InputText type="text" v-model="filterModel.value" @keydown.enter="filterCallback()" class="p-column-filter" placeholder="Search by name"/>
|
||||
|
@ -228,6 +258,8 @@ export default {
|
|||
const loading = ref(false);
|
||||
const totalRecords = ref(0);
|
||||
const customers = ref();
|
||||
const selectedCustomers = ref();
|
||||
const selectAll = ref(false);
|
||||
const customerService = ref(new CustomerService());
|
||||
const filters = ref({
|
||||
'name': {value: '', matchMode: 'contains'},
|
||||
|
@ -269,8 +301,28 @@ export default {
|
|||
lazyParams.value.filters = filters.value ;
|
||||
loadLazyData();
|
||||
}
|
||||
const onSelectAllChange = (event) => {
|
||||
const selectAll = event.checked;
|
||||
|
||||
return { dt, loading, totalRecords, customers, filters, lazyParams, columns, loadLazyData, onPage, onSort, onFilter }
|
||||
if (selectAll) {
|
||||
customerService.value.getCustomers().then(data => {
|
||||
selectAll.value = true;
|
||||
selectedCustomers.value = data.customers;
|
||||
});
|
||||
}
|
||||
else {
|
||||
selectAll.value = false;
|
||||
selectedCustomers.value = [];
|
||||
}
|
||||
}
|
||||
const onRowSelect = () => {
|
||||
selectAll.value = selectedCustomers.value.length === totalRecords.value;
|
||||
}
|
||||
const onRowUnselect = () => {
|
||||
selectAll.value = false;
|
||||
}
|
||||
|
||||
return { dt, loading, totalRecords, customers, filters, lazyParams, columns, loadLazyData, onPage, onSort, onFilter, onSelectAllChange, onRowSelect, onRowUnselect }
|
||||
}
|
||||
}
|
||||
<\\/script>
|
||||
|
@ -282,9 +334,11 @@ export default {
|
|||
<script src="https://unpkg.com/primevue@^3/column/column.min.js"><\\/script>
|
||||
<script src="./CustomerService.js"><\\/script>`,
|
||||
content: `<div id="app">
|
||||
<p-datatable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt"
|
||||
:total-records="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)" @filter="onFilter($event)" filter-display="row"
|
||||
:global-filter-fields="['name','country.name', 'company', 'representative.name']" responsive-layout="scroll">
|
||||
<p-datatable :value="customers" :lazy="true" :paginator="true" :rows="10" v-model:filters="filters" ref="dt" dataKey="id"
|
||||
:totalRecords="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)" @filter="onFilter($event)" filterDisplay="row"
|
||||
:globalFilterFields="['name','country.name', 'company', 'representative.name']" responsiveLayout="scroll"
|
||||
v-model:selection="selectedCustomers" :selectAll="selectAll" @select-all-change="onSelectAllChange" @row-select="onRowSelect" @row-unselect="onRowUnselect">
|
||||
<p-column selectionMode="multiple" headerStyle="width: 3em"></Column>
|
||||
<p-column field="name" header="Name" filter-match-mode="startsWith" ref="name" :sortable="true">
|
||||
<template #filter="{filterModel,filterCallback}">
|
||||
<p-inputtext type="text" v-model="filterModel.value" @keydown.enter="filterCallback()" class="p-column-filter" placeholder="Search by name"></p-inputtext>
|
||||
|
@ -331,6 +385,8 @@ export default {
|
|||
const loading = ref(false);
|
||||
const totalRecords = ref(0);
|
||||
const customers = ref();
|
||||
const selectedCustomers = ref();
|
||||
const selectAll = ref(false);
|
||||
const customerService = ref(new CustomerService());
|
||||
const filters = ref({
|
||||
'name': {value: '', matchMode: 'contains'},
|
||||
|
@ -373,7 +429,28 @@ export default {
|
|||
loadLazyData();
|
||||
}
|
||||
|
||||
return { dt, loading, totalRecords, customers, filters, lazyParams, columns, loadLazyData, onPage, onSort, onFilter }
|
||||
const onSelectAllChange = (event) => {
|
||||
const selectAll = event.checked;
|
||||
|
||||
if (selectAll) {
|
||||
customerService.value.getCustomers().then(data => {
|
||||
selectAll.value = true;
|
||||
selectedCustomers.value = data.customers;
|
||||
});
|
||||
}
|
||||
else {
|
||||
selectAll.value = false;
|
||||
selectedCustomers.value = [];
|
||||
}
|
||||
}
|
||||
const onRowSelect = () => {
|
||||
selectAll.value = selectedCustomers.value.length === totalRecords.value;
|
||||
}
|
||||
const onRowUnselect = () => {
|
||||
selectAll.value = false;
|
||||
}
|
||||
|
||||
return { dt, loading, totalRecords, customers, filters, lazyParams, columns, loadLazyData, onPage, onSort, onFilter, onSelectAllChange, onRowSelect, onRowUnselect }
|
||||
},
|
||||
components: {
|
||||
"p-datatable": primevue.datatable,
|
||||
|
@ -431,6 +508,26 @@ export default {
|
|||
onFilter() {
|
||||
this.lazyParams.filters = this.filters;
|
||||
this.loadLazyData();
|
||||
},
|
||||
onSelectAllChange(event) {
|
||||
const selectAll = event.checked;
|
||||
|
||||
if (selectAll) {
|
||||
this.customerService.getCustomers().then(data => {
|
||||
this.selectAll = true;
|
||||
this.selectedCustomers = data.customers;
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.selectAll = false;
|
||||
this.selectedCustomers = [];
|
||||
}
|
||||
},
|
||||
onRowSelect() {
|
||||
this.selectAll = this.selectedCustomers.length === this.totalRecords
|
||||
},
|
||||
onRowUnselect() {
|
||||
this.selectAll = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
<div class="card">
|
||||
<h5>Checkbox</h5>
|
||||
|
||||
<DataTable :value="products" v-model:selection="selectedProducts3" dataKey="id" responsiveLayout="scroll" >
|
||||
<DataTable :value="products" v-model:selection="selectedProducts3" dataKey="id" responsiveLayout="scroll">
|
||||
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
|
||||
<Column field="code" header="Code"></Column>
|
||||
<Column field="name" header="Name"></Column>
|
||||
|
|
Loading…
Reference in New Issue