I am not sure if this is just not working or I am doing something wrong. I want my column headers and just above a group column to group some of them. Do I have to create my table header in the group as well as I am trying to do in this code or is there any other way to do it. I am getting this error :"Uncaught (in promise) TypeError: Array.prototype.filter called on null or undefined"
Code: Select all
<template>
<div v-if="columns.length > 10" style="height: 100vh">
<DataTable ref="dt" :value="ciclos" :scrollable="true" scrollHeight="flex" class="p-datatable-responsive-demo p-datatable-gridlines"
v-model:selection="selectedProducts1" selectionMode="multiple" dataKey="Fecha">
<template #header>
<div class="p-d-flex p-jc-between">
<div class="p-text-bold">Elección de ciclos</div>
<Button icon="pi pi-external-link" label="Export" class="p-button-sm" @click="exportCSV($event)" />
</div>
</template>
<ColumnGroup type="header">
<Row>
<Column header="H" :colspan="4" />
<Column header="A" :colspan="4" />
<Column header="B" :colspan="4" />
</Row>
<Row>
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" :headerStyle="estiloHeader(col.field)"></Column>
</Row>
</ColumnGroup>
<Column v-for="col of columns" :field="col.field" :key="col.field">
<template #body="slotProps">
<div :class="estiloCelda(slotProps.data, col.field)">
{{ slotProps.data[col.field] }}
</div>
</template>
</Column>
<!-- <Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" :headerStyle="estiloHeader(col.field)">
<template #body="slotProps">
<div :class="estiloCelda(slotProps.data, col.field)">
{{ slotProps.data[col.field] }}
</div>
</template>
</Column> -->
</DataTable>
</div>
<div v-else class="Loading">
<p>Cargando tabla de ciclos...</p>
<br>
<i class="pi pi-spin pi-spinner" style="fontSize: 2rem"></i>
</div>
</template>
<script>
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import Row from 'primevue/row'
import ColumnGroup from 'primevue/columngroup'
import Button from 'primevue/button'
import getCollection from '../composables/getCollection'
import { computed, ref } from 'vue'
export default {
name: 'DetalleCiclos',
components: { DataTable, Column, Button, Row, ColumnGroup },
setup() {
const { error: err1, documents: ciclos } = getCollection('Vs')
const { error: err2, documents: plantilla } = getCollection('Plantilla')
let columns = [null] //no hace falta que sea un ref para mandarlo como parámetro a Column en DataTable
let ordenColumnas = [] //tiene los objectos de plantilla ordenados según la tabla que vamos a mostrar
const camposFijos = ['Ciclo', 'Dia', 'Fecha', 'CupoRRHH', 'Id', 'createdAt', 'V+W']
const selectedProducts1 = ref(null)
const dt = ref(null)
columns = computed(() => {
ordenColumnas = plantilla.value.sort(function(a,b){ //array con las columnas ordenadas según OrdenTabla
return a.OrdenTabla - b.OrdenTabla
})
const columnas = [
{field: 'Ciclo', header: 'Ciclo'},
{field: 'Dia', header: 'Dia'},
{field: 'Fecha', header: 'Fecha'}
]
ordenColumnas.forEach(cta => {
columnas.push({field: cta.Cta, header: cta.Cta})
})
columnas.push(
{field: 'V+W', header: 'V+W'},
{field: 'CupoRRHH', header: 'CupoRRHH'})
return columnas
})
const estiloHeader = (columna) => {
//binding headerStyle a esta función para que el campo fecha sea un poco más ancho
let estilo = ''
if (columna === 'Fecha')
estilo = 'width: 30px'
else
estilo = 'width: 25px'
return estilo
}
const estiloCelda = (data, columna) => {
const estilo = [null]
let cicloPar = true
let ordenCtaTabla = 0
let diaPrimerCiclo = 0
if (!camposFijos.includes(columna)) { //es un campo de cta
//calculo del ciclo al que pertenece el día según grupo del cta
plantilla.value.find((elem) => {
if (elem.Cta == columna){
diaPrimerCiclo = elem.DiaPrimerCiclo
cicloPar = ((Math.floor((data['Id']-diaPrimerCiclo)/8) + 1) % 2) //par o impar
ordenCtaTabla = elem.OrdenTabla //orden del cta en las columnas
}
})
// bordes de las celdas
let bordeDcho = false
if (ordenCtaTabla != ordenColumnas.length) {
if (ordenColumnas[ordenCtaTabla-1]['Grupo'] != ordenColumnas[ordenCtaTabla]['Grupo']) {
bordeDcho = true
}
}
if ( data[columna] === '') //por alguna razón a las casillas vacías no les deja adjuntar ninguna clase
data[columna] = '.'
// w del año anterior, para darle otro color uso w20
let w20 = false
if ( data[columna] === 'w' && diaPrimerCiclo - data['Id'] > 0)
w20 = true
estilo.push([{
'xp': ((data[columna] === 'x') || data[columna] === '.') && cicloPar,
'xi': (data[columna] === 'x' || data[columna] === '.') && !cicloPar,
'V': data[columna] === 'V' || data[columna] === 'w' ,
'V20': data[columna] === 'V20' || w20,
'Va': data[columna] === 'Va',
'Bdcho': bordeDcho
}])
} else {
estilo.push([{
'Fecha': columna === 'Fecha', //clase por defecto para no ctas
'Bdcha': columna === 'Fecha',
'Bizda': columna === 'V+W',
'xp': data['Ciclo'] % 2 === 1,
'xi': data['Ciclo'] % 2 === 0,
'CupoRRHHmm1': columna == 'V+W' && data['CupoRRHH'] - data['V+W'] < -1, //para colorear V+W en funcion de la diferencia con CupoRRHH
'CupoRRHHm1': columna == 'V+W' && data['CupoRRHH'] - data['V+W'] == -1,
'CupoRRHH0': columna == 'V+W' && data['CupoRRHH'] - data['V+W'] == 0,
'CupoRRHH1': columna == 'V+W' && data['CupoRRHH'] - data['V+W'] == 1,
'CupoRRHH2': columna == 'V+W' && data['CupoRRHH'] - data['V+W'] > 1
}])
}
return estilo //devuelve la clase a aplicar a la celda correspondiente
}
const exportCSV = () => {
dt.value.exportCSV()
}
return { ciclos, columns, estiloCelda, estiloHeader, selectedProducts1, exportCSV, dt }
},
}
</script>
<style>
@media screen and (max-width: 600px) {
div.p-datatable-header {
display:none !important;
}
th,td {
font-size: xx-small !important;
}
}
td {
padding: 0 !important;
text-align: center;
font-size: small;
border-color: rgba(104, 152, 224, 0.521) !important;
}
th {
padding: 0 !important;
text-align: center !important;
font-size: small;
font-weight: bold !important;
border-color: rgba(104, 152, 224, 0.521) !important;
}
.table-header {
text-align: center;
}
.p-highlight { /* cambia la manera de mostrar una selección de fila */
filter: brightness(80%);
}
.xp {
background: #e3ecac;
text-align: center;
}
.xi {
background: #c9ffc4d5;
text-align: center;
border-spacing: 0px !important;
}
.V {
background: #1f720a;
color:rgb(255, 255, 255);
text-align: center;
}
.V20 {
background: #b36dbd;
color:rgb(10, 10, 10);
text-align: center;
}
.Va {
background: #000000;
color:rgb(255, 255, 255);
text-align: center;
}
.Fecha {
white-space: nowrap;
}
.CupoRRHHmm1{
background: blueviolet;
}
.CupoRRHHm1{
background: rgb(226, 43, 43);
}
.CupoRRHH0{
background: rgb(8, 214, 77);
}
.CupoRRHH1{
background: rgb(241, 204, 240);
}
.CupoRRHH2{
background: rgb(207, 100, 207);
}
.Bdcha{
border-right: solid;
border-color: black;
}
.Bizda{
border-left: solid;
border-color: black;
}
.Loading{
margin: auto;
text-align: center;
width: 50%;
}
</style>