xref: /openbmc/webui-vue/src/components/Mixins/BVTableSelectableMixin.js (revision d36ac8a8be8636ddd0e64ce005d507b21bcdeb00)
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