I am using Pinia to manage the state of different DataTables throughout my application. It’s possible for multiple tables to be opened “on top” of each other (i.e. in overlay(s) over each other). This is why I am reworking our current setup where only 1 table can be opened and another table would overwrite the previous table, to a new system where multiple tables can be opened at the same time.
I thought of using Pinia with a Map() to keep all my data table configurations in place, and make use of a “activeDataTableName” field to keep track of which table is currently the ‘active’ one.
My Pinia store looks like this:
export const useDataTableStore = defineStore('data-table', {
state: () => ({
dataTables: new Map(), // use a Map to store all data table configurations
activeDataTableName: null, // Used to track which is the current active data table
}),
getters: {
getActiveDataTableConfig: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig || null
},
getDataTableName: (state) => state.activeDataTableName,
getLoading: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.loading : true
},
getDataTableColumns: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.dataTableColumns : []
},
getTotalRecords: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.totalRecords : 0
},
getFirst: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.first : 0
},
getAmountRowsToShow: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.amountRowsToShow : 15
},
getSelectedRows: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.selectedRows : []
},
getFocussedRow: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.focussedRow : null
},
getLazyParams: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.lazyParams: {}
}
getSelectAll: (state) => {
const dtConfig = state.dataTables.get(state.activeDataTableName)
return dtConfig ? dtConfig.selectAll : false
},
},
actions: {
async initialize (nuxtApp, dtName) {
// The initialize function sets the dataTableName and loads the columns
const newDataTableConfigObject = {
loading: true,
dataTableName: dtName,
dataTableColumns: [],
totalRecords: 0,
first: 0,
amountRowsToShow: 15,
selectedRows: [],
focussedRow: null,
lazyParams: {},
selectAll: false,
}
this.dataTables.set(dtName, newDataTableConfigObject)
this.activeDataTableName = dtName
},
setSelectedRows (rows) {
const dtConfig = this.dataTables.get(this.activeDataTableName)
if (dtConfig) {
dtConfig.selectedRows = rows
}
},
},
})
My problems arise when I am trying to do the 2-way binding in using v-model.
Eg: i’ll have a component “DataTable” which takes in the values from my store in a v-model as so :
<DataTable
ref="dataTableRef"
v-model:selection="store.selectedRows"
v-model:first="store.first"
v-model:rows="store.amountRowsToShow"
...
/>
when my store is initialised:
const store = useDataTableStore()
the values of “selectedRows”, “first” etc. will not be directly in the store, but rather in the active configuration object inside dataTables in the store.
I’m also struggling when trying to set values to the store’s variables:
store.amountRowsToShow = rows
store.lazyParams.first = store.getFirst
store.lazyParams.rows = store.getAmountRowsToShow
this can probably be solved with specific setters for each of them, but if I have to create a setter method for each potential object inside lazyParams, it becomes very tedious. Isn’t there a better approach to this?