primefaces / primevue

Next Generation Vue UI Component Library
https://primevue.org
MIT License
10.08k stars 1.2k forks source link

Column: Custom Column not recognized by DataTable #4940

Open moyoakala opened 10 months ago

moyoakala commented 10 months ago

Describe the bug

I created a custom column because I do not want to repeat the default props for columns in all the tables

<script lang="ts" setup>
import Column from 'primevue/column'

defineProps({
  header: {
    type: String,
    default: '',
  },
  sortable: {
    type: Boolean,
    default: true,
  },
  showFilterMatchModes: {
    type: Boolean,
    default: false,
  },
})
</script>

<template>
  <Column
    :header="field"
    :sortable="sortable"
    :show-filter-match-modes="showFilterMatchModes"
  >
    <slot name="body" />
    <slot name="filter" />
  </Column>
</template>

This BaseColumn is imported in another compoent

<script lang="ts" setup>
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import BaseColumn from '../base/table/BaseColumn.vue'
</script>
<template>
  <DataTable
     v-model:filters="filters"
     :value="data"
  >
    <BaseColumn field="description" header="Description">
      <template #body="row">
        {{  row.data.description  }}
      </template>
    </BaseColumn>
    <Column field="description" header="Description">
      <template #body="row">
        {{  row.data.description  }}
      </template>
    </Column>
  </DataTable>

In my table, I see this column from the Column component but I do not see that of the BaseColumn component. The same behaviour happens when you create a custom table with expandable rows. The custom table in your expansion template is not recognized by the parent datatable

Reproducer

https://codesandbox.io/p/sandbox/gifted-alex-sx5clg

PrimeVue version

3.45.0

Vue version

3.x

Language

TypeScript

Build / Runtime

Vue CLI App

Browser(s)

No response

Steps to reproduce the behavior

No response

Expected behavior

I expect the BaseColumn to work just like the Column component same for the tables with expandable rows.

tugcekucukoglu commented 10 months ago

Please track this ticket: #4646

moyoakala commented 9 months ago

@tugcekucukoglu @mertsincan this does not seem to be working with the latest version. I can't get it to work in the reproducer (https://codesandbox.io/p/sandbox/gifted-alex-sx5clg).

mertsincan commented 9 months ago

Thanks @moyoakala, I'll check it.

mertsincan commented 8 months ago

I moved it to the next milestone to work on it in more detail.

mertsincan commented 8 months ago

Update: I'm working on this issue.

moyoakala commented 8 months ago

Update: I'm working on this issue.

Thanks @mertsincan. I created a sadbox environment of what I think should work but does not. I invited you here A custom column is not recognized within a custom datatable. A custom component is also not recognized within a custom column

tugcekucukoglu commented 7 months ago

We need more time to investigate this issue. I am setting a new milestone.

Thank you.

cybearz commented 4 months ago

Any updates?

luizottavioc commented 4 months ago

I want to know too

Thiritin commented 3 months ago

It appears to work IF you add a v-if condition to your DataTable Body. See here https://github.com/primefaces/primevue/issues/4646#issuecomment-2179784004

tjbrains commented 3 months ago

same issue appears in 4.0.0 rc.2

serhiismt commented 1 month ago

Hello! Are there any plans to fix it in the near future? Thanks for the answer

iwind commented 1 month ago

Finally, i found a way to implement custom column:

TDataTable:

<script setup>
...

// dynamic columns
const columns = ref([])
provide("$t_columns", columns.value)

</script>

<template>
    <DataTable>
        <slot></slot>

        <template v-for="column in columns">
            <Column v-bind="column.instance.props">
                <template v-for="(slot, slotName) in column.instance.slots" :key="slotName" #[slotName]="slotProps">
                    <Component :is="slot" v-bind="slotProps"/>
                </template>
            </Column>
        </template>
    </DataTable>
</template>

<style scoped>

</style>

TColumn:

<script setup lang="ts">
import {getCurrentInstance, inject} from "vue";
import {ColumnSlots} from "primevue/column";

const props = defineProps({
    columnKey: {
        type: null,
        default: null
    },
    field: {
        type: [String, Function],
        default: null
    },
    sortField: {
        type: [String, Function],
        default: null
    },
    filterField: {
        type: [String, Function],
        default: null
    },
    dataType: {
        type: String,
        default: 'text'
    },
    sortable: {
        type: Boolean,
        default: false
    },
    header: {
        type: null,
        default: null
    },
    footer: {
        type: null,
        default: null
    },
    style: {
        type: null,
        default: null
    },
    class: {
        type: String,
        default: null
    },
    headerStyle: {
        type: null,
        default: null
    },
    headerClass: {
        type: String,
        default: null
    },
    bodyStyle: {
        type: null,
        default: null
    },
    bodyClass: {
        type: String,
        default: null
    },
    footerStyle: {
        type: null,
        default: null
    },
    footerClass: {
        type: String,
        default: null
    },
    showFilterMenu: {
        type: Boolean,
        default: true
    },
    showFilterOperator: {
        type: Boolean,
        default: true
    },
    showClearButton: {
        type: Boolean,
        default: true
    },
    showApplyButton: {
        type: Boolean,
        default: true
    },
    showFilterMatchModes: {
        type: Boolean,
        default: true
    },
    showAddButton: {
        type: Boolean,
        default: true
    },
    filterMatchModeOptions: {
        type: Array,
        default: null
    },
    maxConstraints: {
        type: Number,
        default: 2
    },
    excludeGlobalFilter: {
        type: Boolean,
        default: false
    },
    filterHeaderClass: {
        type: String,
        default: null
    },
    filterHeaderStyle: {
        type: null,
        default: null
    },
    filterMenuClass: {
        type: String,
        default: null
    },
    filterMenuStyle: {
        type: null,
        default: null
    },
    selectionMode: {
        type: String,
        default: null
    },
    expander: {
        type: Boolean,
        default: false
    },
    colspan: {
        type: Number,
        default: null
    },
    rowspan: {
        type: Number,
        default: null
    },
    rowReorder: {
        type: Boolean,
        default: false
    },
    rowReorderIcon: {
        type: String,
        default: undefined
    },
    reorderableColumn: {
        type: Boolean,
        default: true
    },
    rowEditor: {
        type: Boolean,
        default: false
    },
    frozen: {
        type: Boolean,
        default: false
    },
    alignFrozen: {
        type: String,
        default: 'left'
    },
    exportable: {
        type: Boolean,
        default: true
    },
    exportHeader: {
        type: String,
        default: null
    },
    exportFooter: {
        type: String,
        default: null
    },
    filterMatchMode: {
        type: String,
        default: null
    },
    hidden: {
        type: Boolean,
        default: false
    }
})

const instance = getCurrentInstance()
const columns = inject("$t_columns")
columns.push({
    instance: instance
})

const slots = defineSlots<ColumnSlots>()
</script>

<template>
    <template></template>
</template>

<style scoped>

</style>

Now you can use TColumn to replace Column:

<TDataTable>
   <TColumn header="Column Header 1">
         <template #body>...</template>
   </TColumn>
   <TColumn header="Column Header 2">
        <template #body>...</template>
   </TColumn>
   <!-- other columns -->
</TDataTable>