I am using primevue datatable to show my data, and row expansion to show additional details. https://primevue.org/datatable/#row_expansion
My problem is that some of the rows have no data in expanded row (blue T-shirt in example), and I would love this whole row to be hidden.
Lets say I have no control over data I receive, I can just edit frontend.
Example what I have: https://codesandbox.io/p/sandbox/primevue-demo-forked-3sn4wz
So I want that the row with blue T-shirt would be completely hidden/gone. Is there any easy way to do that?
I tried doing that in CSS but I can hide expanded row which contains no data (using has()
selector) but I cannot get rid of the main row:
In the future I plan to use it to add filtering, and once user filters out everything from details, I want to hide main row as well
My try with CSS was:
.p-datatable-row-expansion:has(.p-datatable-emptymessage) {
display: none;
}
EDIT:
My newest try was to watch for filter variable change, and then just hide rows using javascript. Unfortunately hiding occurs before filtering, leaving sometimes empty expanded rows, and hiding them one input later.
Part of code I added:
watch(filters.value["global"], (newValue, oldValue) => {
console.log(newValue, oldValue);
xxxx();
});
Is there a filtering callback function after its done?
Code: https://codesandbox.io/p/sandbox/primevue-demo-forked-844j47
a filter will solve this problem:
<template>
<div class="card">
<DataTable
v-model:expandedRows="expandedRows"
:value="products?.filter((item) => item.orders.length > 0)"
dataKey="id"
tableStyle="min-width: 60rem"
>
...
if you want to filter advanced functions based on filters
like PrimeVue
you have to add it:
import { FilterMatchMode, FilterService } from "primevue/api";
import { ObjectUtils } from 'primevue/utils';
// your filters
const filters = ref({
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
name: { value: null, matchMode: FilterMatchMode.STARTS_WITH },
"country.name": { value: null, matchMode: FilterMatchMode.STARTS_WITH },
representative: { value: null, matchMode: FilterMatchMode.IN },
status: { value: null, matchMode: FilterMatchMode.EQUALS },
verified: { value: null, matchMode: FilterMatchMode.EQUALS },
});
const productsFilterFn = ({ orders }) => {
if (!orders.length) return false
return orders.some(order => {
for (const prop in order) {
const type = filters.value[prop] ?? filters.value.global
if (type.matchMode === FilterMatchMode.EQUALS)
return ObjectUtils.resolveFieldData(order, prop) === type.value
if (FilterService.filters[type.matchMode](ObjectUtils.resolveFieldData(order, prop), type.value)) {
return true
}
}
return false
})
}
and use fn:
<template>
<div class="card">
<DataTable
v-model:expandedRows="expandedRows"
:value="products?.filter(productsFilterFn)"
dataKey="id"
tableStyle="min-width: 60rem"
>
...