blob: f0a52600c6d6361bae1dcb2c8b430ff41ec1fcd9 [file] [log] [blame]
Nishant Tiwarid3b05032026-01-28 20:18:48 +05301/**
2 * Composable for table selection utilities
3 * Extracted from BVTableSelectableMixin for use in Composition API
4 */
5
6import { ref, nextTick, watch } from 'vue';
7
8export function useTableSelection(currentPage = ref(1)) {
9 const selectedRows = ref([]);
10 const tableHeaderCheckboxModel = ref(false);
11 const tableHeaderCheckboxIndeterminate = ref(false);
12
13 // Watch for page changes and clear selections
14 // This prevents confusion with checkboxes appearing checked on the new page
15 watch(currentPage, (newPage, oldPage) => {
16 if (newPage !== oldPage) {
17 selectedRows.value = [];
18 tableHeaderCheckboxModel.value = false;
19 tableHeaderCheckboxIndeterminate.value = false;
20 }
21 });
22
23 const clearSelectedRows = (tableRef) => {
24 if (tableRef) {
25 tableRef.clearSelected();
26 selectedRows.value = [];
27 tableHeaderCheckboxModel.value = false;
28 tableHeaderCheckboxIndeterminate.value = false;
29 }
30 };
31
32 const toggleSelectRow = (tableRef, rowIndex) => {
33 if (tableRef && rowIndex !== undefined) {
34 const wasSelected = tableRef.isRowSelected(rowIndex);
35
36 if (wasSelected) {
37 tableRef.unselectRow(rowIndex);
38 } else {
39 tableRef.selectRow(rowIndex);
40 }
41
42 nextTick(() => {
43 onRowSelected(tableRef);
44 });
45 }
46 };
47
48 const onRowSelected = (tableRef) => {
49 if (!tableRef) return;
50
51 const allItems = tableRef.filteredItems || tableRef.items || [];
52 const selectedItems = allItems.filter((item, index) => {
53 return tableRef.isRowSelected(index);
54 });
55
56 selectedRows.value = selectedItems;
57
58 const currentPage = 1;
59 const perPage = allItems.length;
60 const startIndex = (currentPage - 1) * perPage;
61 const endIndex = Math.min(startIndex + perPage, allItems.length);
62 const pageItemsCount = endIndex - startIndex;
63
64 const selectedOnPageCount = selectedItems.filter((item) =>
65 allItems
66 .slice(startIndex, endIndex)
67 .some((pageItem) => pageItem === item),
68 ).length;
69
70 if (selectedOnPageCount === 0) {
71 tableHeaderCheckboxIndeterminate.value = false;
72 tableHeaderCheckboxModel.value = false;
73 } else if (selectedOnPageCount === pageItemsCount) {
74 tableHeaderCheckboxIndeterminate.value = false;
75 tableHeaderCheckboxModel.value = true;
76 } else {
77 tableHeaderCheckboxIndeterminate.value = true;
78 tableHeaderCheckboxModel.value = true;
79 }
80 };
81
82 const onChangeHeaderCheckbox = (tableRef, event) => {
83 /*
84 * Bootstrap Vue Next Migration:
85 * Handle header checkbox to select/deselect all rows on current page.
86 */
87 if (!tableRef) return;
88
89 const isChecked =
90 typeof event === 'boolean' ? event : event?.target?.checked;
91
92 if (isChecked) {
93 const allItems = tableRef.filteredItems || tableRef.items || [];
94 const endIndex = allItems.length;
95
96 for (let i = 0; i < endIndex; i++) {
97 tableRef.selectRow(i);
98 }
99 } else {
100 tableRef.clearSelected();
101 selectedRows.value = [];
102 tableHeaderCheckboxModel.value = false;
103 tableHeaderCheckboxIndeterminate.value = false;
104 }
105
106 nextTick(() => {
107 onRowSelected(tableRef);
108 });
109 };
110
111 return {
112 selectedRows,
113 tableHeaderCheckboxModel,
114 tableHeaderCheckboxIndeterminate,
115 clearSelectedRows,
116 toggleSelectRow,
117 onRowSelected,
118 onChangeHeaderCheckbox,
119 };
120}