| export const selectedRows = []; |
| export const tableHeaderCheckboxModel = false; |
| export const tableHeaderCheckboxIndeterminate = false; |
| |
| const BVTableSelectableMixin = { |
| data() { |
| return { |
| selectedRows: [], |
| tableHeaderCheckboxModel: false, |
| tableHeaderCheckboxIndeterminate: false, |
| }; |
| }, |
| watch: { |
| currentPage() { |
| // Bootstrap Vue 2 behavior: Clear selections when page changes |
| // This prevents confusion with checkboxes appearing checked on the new page |
| const table = this.$refs.table; |
| if (table) { |
| table.clearSelected(); |
| this.selectedRows = []; |
| this.tableHeaderCheckboxModel = false; |
| this.tableHeaderCheckboxIndeterminate = false; |
| } |
| }, |
| }, |
| methods: { |
| clearSelectedRows(tableRef) { |
| if (tableRef) { |
| tableRef.clearSelected(); |
| this.selectedRows = []; |
| this.tableHeaderCheckboxModel = false; |
| this.tableHeaderCheckboxIndeterminate = false; |
| } |
| }, |
| toggleSelectRow(tableRef, rowIndex) { |
| if (tableRef && rowIndex !== undefined) { |
| const wasSelected = tableRef.isRowSelected(rowIndex); |
| |
| if (wasSelected) { |
| tableRef.unselectRow(rowIndex); |
| } else { |
| tableRef.selectRow(rowIndex); |
| } |
| |
| // Manually trigger onRowSelected after toggle since unselectRow might not fire event |
| this.$nextTick(() => { |
| this.onRowSelected(); |
| }); |
| } |
| }, |
| onRowSelected() { |
| /* |
| * Bootstrap Vue Next fires @row-selected for each individual row change. |
| * Query the table's internal state to get ALL currently selected rows. |
| */ |
| const table = this.$refs.table; |
| if (!table) return; |
| |
| const allItems = table.filteredItems || table.items || []; |
| const selectedItems = allItems.filter((item, index) => { |
| return table.isRowSelected(index); |
| }); |
| |
| this.selectedRows = selectedItems; |
| |
| // Update header checkbox state |
| const currentPage = this.currentPage || 1; |
| const perPage = this.perPage || 10; |
| const startIndex = (currentPage - 1) * perPage; |
| const endIndex = Math.min(startIndex + perPage, allItems.length); |
| const pageItemsCount = endIndex - startIndex; |
| |
| const selectedOnPageCount = selectedItems.filter((item) => |
| allItems |
| .slice(startIndex, endIndex) |
| .some((pageItem) => pageItem === item), |
| ).length; |
| |
| if (selectedOnPageCount === 0) { |
| this.tableHeaderCheckboxIndeterminate = false; |
| this.tableHeaderCheckboxModel = false; |
| } else if (selectedOnPageCount === pageItemsCount) { |
| this.tableHeaderCheckboxIndeterminate = false; |
| this.tableHeaderCheckboxModel = true; |
| } else { |
| this.tableHeaderCheckboxIndeterminate = true; |
| this.tableHeaderCheckboxModel = true; |
| } |
| }, |
| onChangeHeaderCheckbox(tableRef, event) { |
| /* |
| * Bootstrap Vue Next Migration: |
| * Handle header checkbox to select/deselect all rows on current page. |
| */ |
| if (!tableRef) return; |
| |
| // Extract checked state from event (could be boolean or Event object) |
| const isChecked = |
| typeof event === 'boolean' ? event : event?.target?.checked; |
| |
| if (isChecked) { |
| // Select all rows on the current page |
| const currentPage = this.currentPage || 1; |
| const perPage = this.perPage || 10; |
| const startIndex = (currentPage - 1) * perPage; |
| const allItems = tableRef.filteredItems || tableRef.items || []; |
| const endIndex = Math.min(startIndex + perPage, allItems.length); |
| |
| for (let i = startIndex; i < endIndex; i++) { |
| tableRef.selectRow(i); |
| } |
| } else { |
| // Deselect all rows |
| tableRef.clearSelected(); |
| // Manually trigger update since clearSelected might not fire @row-selected |
| this.selectedRows = []; |
| this.tableHeaderCheckboxModel = false; |
| this.tableHeaderCheckboxIndeterminate = false; |
| } |
| |
| // onRowSelected will be triggered automatically for selections |
| }, |
| }, |
| }; |
| |
| export default BVTableSelectableMixin; |