I’ve the following source:
<code><template lang="pug">
Dialog(:visible="$show" modal :style="{ width: '60vw' }" :breakpoints="{ '960px': '75vw', '641px': '100vw' }" @show="fnLoadTypes" @update:visible="fnHide")
Dropdown.mt-1.mb-1.w-full(v-model="$typeId" filter :options="$types" :loading="$loading.types" :disabled="$loading.types" optionValue="gitlabId" optionLabel="name")
DataTable(v-if="$plugins.length" :value="$plugins" :loading="$loading.plugins" v-model:selection="$selected" dataKey="component" paginator :rows="5" :rowsPerPageOptions="[5, 10, 20, 50]" @page="fnLoadPlugins" :totalRecords="$totalPlugins" lazy)
Column(selectionMode="multiple" headerStyle="width: 3rem")
Column.w-4(field="name" header="Name")
Column.w-8(header="Reference")
template(#body="{data, index}")
Dropdown.w-full(v-model="data.ref" :disabled="!$selected.some($p => $p.component === data.component)")
Button(label="Install Plugins" :disabled="!$selected.length")
fa.mr-1(icon="fa-solid fa-plug-circle-check")
import { ref, inject, watch } from 'vue'
const $api = inject('api')
const $selected = ref([])
const $lazyParams = ref({
const $totalPlugins = ref(0)
const $emit = defineEmits(['update:show'])
const $props = defineProps({
watch($typeId, async() => {
fnLoadPlugins({ page: 0 })
watch(() => $props.show, ($value) => {
async function fnHide($event) {
$emit('update:show', $event)
async function fnLoadPlugins($event) {
// This is necessary because when the dialog closes, it sets the value of $typeId to null.
// Following this, the watch() for $typeid calls fnLoadPlugins() which results in a call for plugin-types where $typeId is null.
if (typeof $typeId.value !== 'number') {
if (typeof $event?.page === 'number') {
$lazyParams.value.page = Number($event.page)
if (typeof $event?.rows === 'number') {
$lazyParams.value.perPage = Number($event.rows)
$lazyParams.value.sort = { '-1': 'asc', 1: 'desc' }[$event.sortOrder]
// Because API expects first page to be 1 and not 0...
$lazyParams.value.page += 1
$loading.value.plugins = true
const $axios = await $api.get(`/getplugins`, {
params: $lazyParams.value
$loading.value.plugins = false
if ($axios.status === 200) {
$plugins.value = $axios.data
$totalPlugins.value = Number($axios.headers['x-total'])
async function fnLoadTypes() {
$loading.value.types = true
const $axios = await $api.get('/gettypes', {
params: { orderBy: 'path' }
$loading.value.types = false
if ($axios.status === 200) {
$types.value = $axios.data
<code><template lang="pug">
Dialog(:visible="$show" modal :style="{ width: '60vw' }" :breakpoints="{ '960px': '75vw', '641px': '100vw' }" @show="fnLoadTypes" @update:visible="fnHide")
template(#default)
Dropdown.mt-1.mb-1.w-full(v-model="$typeId" filter :options="$types" :loading="$loading.types" :disabled="$loading.types" optionValue="gitlabId" optionLabel="name")
DataTable(v-if="$plugins.length" :value="$plugins" :loading="$loading.plugins" v-model:selection="$selected" dataKey="component" paginator :rows="5" :rowsPerPageOptions="[5, 10, 20, 50]" @page="fnLoadPlugins" :totalRecords="$totalPlugins" lazy)
Column(selectionMode="multiple" headerStyle="width: 3rem")
Column.w-4(field="name" header="Name")
Column.w-8(header="Reference")
template(#body="{data, index}")
Dropdown.w-full(v-model="data.ref" :disabled="!$selected.some($p => $p.component === data.component)")
template(#footer)
Button(label="Install Plugins" :disabled="!$selected.length")
template(#icon)
fa.mr-1(icon="fa-solid fa-plug-circle-check")
</template>
<script setup>
import { ref, inject, watch } from 'vue'
const $show = ref(false)
const $api = inject('api')
const $types = ref([])
const $typeId = ref()
const $plugins = ref([])
const $selected = ref([])
const $loading = ref({
types: false,
plugins: false
})
const $lazyParams = ref({
perPage: 5,
orderBy: 'name'
})
const $totalPlugins = ref(0)
const $emit = defineEmits(['update:show'])
const $props = defineProps({
show: {
type: Boolean,
default: false
}
})
watch($typeId, async() => {
fnLoadPlugins({ page: 0 })
})
watch(() => $props.show, ($value) => {
$show.value = $value
})
async function fnHide($event) {
$emit('update:show', $event)
$lazyParams.value = {
perPage: 5,
orderBy: 'name'
}
$typeId.value = null
$plugins.value = []
$selected.value = []
}
async function fnLoadPlugins($event) {
//
// This is necessary because when the dialog closes, it sets the value of $typeId to null.
// Following this, the watch() for $typeid calls fnLoadPlugins() which results in a call for plugin-types where $typeId is null.
if (typeof $typeId.value !== 'number') {
return
}
if (typeof $event?.page === 'number') {
$lazyParams.value.page = Number($event.page)
}
if (typeof $event?.rows === 'number') {
$lazyParams.value.perPage = Number($event.rows)
}
if ($event?.sortOrder) {
$lazyParams.value.sort = { '-1': 'asc', 1: 'desc' }[$event.sortOrder]
}
// Because API expects first page to be 1 and not 0...
$lazyParams.value.page += 1
$loading.value.plugins = true
const $axios = await $api.get(`/getplugins`, {
params: $lazyParams.value
})
$loading.value.plugins = false
if ($axios.status === 200) {
$plugins.value = $axios.data
$totalPlugins.value = Number($axios.headers['x-total'])
} else {
// TODO: Error-Handling
}
}
async function fnLoadTypes() {
$loading.value.types = true
const $axios = await $api.get('/gettypes', {
params: { orderBy: 'path' }
})
$loading.value.types = false
if ($axios.status === 200) {
$types.value = $axios.data
} else {
// TODO: Error Handling
}
}
</script>
</code>
<template lang="pug">
Dialog(:visible="$show" modal :style="{ width: '60vw' }" :breakpoints="{ '960px': '75vw', '641px': '100vw' }" @show="fnLoadTypes" @update:visible="fnHide")
template(#default)
Dropdown.mt-1.mb-1.w-full(v-model="$typeId" filter :options="$types" :loading="$loading.types" :disabled="$loading.types" optionValue="gitlabId" optionLabel="name")
DataTable(v-if="$plugins.length" :value="$plugins" :loading="$loading.plugins" v-model:selection="$selected" dataKey="component" paginator :rows="5" :rowsPerPageOptions="[5, 10, 20, 50]" @page="fnLoadPlugins" :totalRecords="$totalPlugins" lazy)
Column(selectionMode="multiple" headerStyle="width: 3rem")
Column.w-4(field="name" header="Name")
Column.w-8(header="Reference")
template(#body="{data, index}")
Dropdown.w-full(v-model="data.ref" :disabled="!$selected.some($p => $p.component === data.component)")
template(#footer)
Button(label="Install Plugins" :disabled="!$selected.length")
template(#icon)
fa.mr-1(icon="fa-solid fa-plug-circle-check")
</template>
<script setup>
import { ref, inject, watch } from 'vue'
const $show = ref(false)
const $api = inject('api')
const $types = ref([])
const $typeId = ref()
const $plugins = ref([])
const $selected = ref([])
const $loading = ref({
types: false,
plugins: false
})
const $lazyParams = ref({
perPage: 5,
orderBy: 'name'
})
const $totalPlugins = ref(0)
const $emit = defineEmits(['update:show'])
const $props = defineProps({
show: {
type: Boolean,
default: false
}
})
watch($typeId, async() => {
fnLoadPlugins({ page: 0 })
})
watch(() => $props.show, ($value) => {
$show.value = $value
})
async function fnHide($event) {
$emit('update:show', $event)
$lazyParams.value = {
perPage: 5,
orderBy: 'name'
}
$typeId.value = null
$plugins.value = []
$selected.value = []
}
async function fnLoadPlugins($event) {
//
// This is necessary because when the dialog closes, it sets the value of $typeId to null.
// Following this, the watch() for $typeid calls fnLoadPlugins() which results in a call for plugin-types where $typeId is null.
if (typeof $typeId.value !== 'number') {
return
}
if (typeof $event?.page === 'number') {
$lazyParams.value.page = Number($event.page)
}
if (typeof $event?.rows === 'number') {
$lazyParams.value.perPage = Number($event.rows)
}
if ($event?.sortOrder) {
$lazyParams.value.sort = { '-1': 'asc', 1: 'desc' }[$event.sortOrder]
}
// Because API expects first page to be 1 and not 0...
$lazyParams.value.page += 1
$loading.value.plugins = true
const $axios = await $api.get(`/getplugins`, {
params: $lazyParams.value
})
$loading.value.plugins = false
if ($axios.status === 200) {
$plugins.value = $axios.data
$totalPlugins.value = Number($axios.headers['x-total'])
} else {
// TODO: Error-Handling
}
}
async function fnLoadTypes() {
$loading.value.types = true
const $axios = await $api.get('/gettypes', {
params: { orderBy: 'path' }
})
$loading.value.types = false
if ($axios.status === 200) {
$types.value = $axios.data
} else {
// TODO: Error Handling
}
}
</script>
The Dropdown in the “Reference” column should be enabled/disabled depending on the row selection. My problem is, when I check (enable) a row, select the value from the dropdown, go to another page (which triggers the fnLoadPlugins). When I go back to the previous page, the row is still checked, but the value in the dropdown is gone. The reason is that I’m using data.ref
as v-model for the dropdown which is overwritten whenever the function fnLoadPlugins is being called. So in theory I would use $selected instead of data.ref, but in the #body
slot of the “Reference” column I don’t know the corresponding entry in the “$selected” array (because it might be not selected).
I already thought about replacing the DataTable selection by rendering my own Checkboxes with my own callbacks, but in this case the problem is that I cannot set the checkbox checked because the corresponding value might not exist in the $selected array… so my v-model would be undefined.
So I wonder how if anyone has an idea how to solve this issue…