1export const selectedRows = []; 2export const tableHeaderCheckboxModel = false; 3export const tableHeaderCheckboxIndeterminate = false; 4 5const BVTableSelectableMixin = { 6 data() { 7 return { 8 selectedRows: [], 9 tableHeaderCheckboxModel: false, 10 tableHeaderCheckboxIndeterminate: false, 11 }; 12 }, 13 watch: { 14 currentPage() { 15 // Bootstrap Vue 2 behavior: Clear selections when page changes 16 // This prevents confusion with checkboxes appearing checked on the new page 17 const table = this.$refs.table; 18 if (table) { 19 table.clearSelected(); 20 this.selectedRows = []; 21 this.tableHeaderCheckboxModel = false; 22 this.tableHeaderCheckboxIndeterminate = false; 23 } 24 }, 25 }, 26 methods: { 27 clearSelectedRows(tableRef) { 28 if (tableRef) { 29 tableRef.clearSelected(); 30 this.selectedRows = []; 31 this.tableHeaderCheckboxModel = false; 32 this.tableHeaderCheckboxIndeterminate = false; 33 } 34 }, 35 toggleSelectRow(tableRef, rowIndex) { 36 if (tableRef && rowIndex !== undefined) { 37 const wasSelected = tableRef.isRowSelected(rowIndex); 38 39 if (wasSelected) { 40 tableRef.unselectRow(rowIndex); 41 } else { 42 tableRef.selectRow(rowIndex); 43 } 44 45 // Manually trigger onRowSelected after toggle since unselectRow might not fire event 46 this.$nextTick(() => { 47 this.onRowSelected(); 48 }); 49 } 50 }, 51 onRowSelected() { 52 /* 53 * Bootstrap Vue Next fires @row-selected for each individual row change. 54 * Query the table's internal state to get ALL currently selected rows. 55 */ 56 const table = this.$refs.table; 57 if (!table) return; 58 59 const allItems = table.filteredItems || table.items || []; 60 const selectedItems = allItems.filter((item, index) => { 61 return table.isRowSelected(index); 62 }); 63 64 this.selectedRows = selectedItems; 65 66 // Update header checkbox state 67 const currentPage = this.currentPage || 1; 68 const perPage = this.perPage || 10; 69 const startIndex = (currentPage - 1) * perPage; 70 const endIndex = Math.min(startIndex + perPage, allItems.length); 71 const pageItemsCount = endIndex - startIndex; 72 73 const selectedOnPageCount = selectedItems.filter((item) => 74 allItems 75 .slice(startIndex, endIndex) 76 .some((pageItem) => pageItem === item), 77 ).length; 78 79 if (selectedOnPageCount === 0) { 80 this.tableHeaderCheckboxIndeterminate = false; 81 this.tableHeaderCheckboxModel = false; 82 } else if (selectedOnPageCount === pageItemsCount) { 83 this.tableHeaderCheckboxIndeterminate = false; 84 this.tableHeaderCheckboxModel = true; 85 } else { 86 this.tableHeaderCheckboxIndeterminate = true; 87 this.tableHeaderCheckboxModel = true; 88 } 89 }, 90 onChangeHeaderCheckbox(tableRef, event) { 91 /* 92 * Bootstrap Vue Next Migration: 93 * Handle header checkbox to select/deselect all rows on current page. 94 */ 95 if (!tableRef) return; 96 97 // Extract checked state from event (could be boolean or Event object) 98 const isChecked = 99 typeof event === 'boolean' ? event : event?.target?.checked; 100 101 if (isChecked) { 102 // Select all rows on the current page 103 const currentPage = this.currentPage || 1; 104 const perPage = this.perPage || 10; 105 const startIndex = (currentPage - 1) * perPage; 106 const allItems = tableRef.filteredItems || tableRef.items || []; 107 const endIndex = Math.min(startIndex + perPage, allItems.length); 108 109 for (let i = startIndex; i < endIndex; i++) { 110 tableRef.selectRow(i); 111 } 112 } else { 113 // Deselect all rows 114 tableRef.clearSelected(); 115 // Manually trigger update since clearSelected might not fire @row-selected 116 this.selectedRows = []; 117 this.tableHeaderCheckboxModel = false; 118 this.tableHeaderCheckboxIndeterminate = false; 119 } 120 121 // onRowSelected will be triggered automatically for selections 122 }, 123 }, 124}; 125 126export default BVTableSelectableMixin; 127