primevue
primevue copied to clipboard
Component Name: DataTable (possibly others)
Describe the feature you would like to see added
using dynamic vue <component />
s as wrappers to encapsulate logic, DRY up and SOLIDify my app.
Is your feature request related to a problem?
Firstly, sorry if this is documented elsewhere (or should be posted somewhere else for that matter). I've spent a good while crawling through the docs and google and couldn't find anything. I also really like the library as it feels a lot more in-line with vue best practices than a lot of the others I've used.
I'm currently implementing some DataTables for a project.
There is a lot of shared functionality so I'd like to abstract everything into a generic table component that can be called from anywhere in my app.
I have got it working but it has now become quite messy. And it's only going to get messier.
As the main variance of functionality seems to happen at the column level (filter behaviour for example), I was thinking I'd extract the (dynamic) <Column />
components into a wrapper that can take the column metadata and generically apply whatever rules are associated.
For example, I have an <SelecteColumn />
component that sets showFilterMatchModes
and showFilterOperator
to false and set's up a MultiSelect
filter.
So instead of iterating through my columns and handling each case separately, it would be nice to have the correct column type render. I'm assuming that I need to bind some properties of the parent <DataTable />
component but I don't know what they are.
I'm not getting any errors in the console but I'm not getting any data showing either.
Describe the solution you'd like
It could (I hope) just be some documentation that's required.
Describe alternatives you have considered
I'll add some code below, to give an example of what I've done
Additional context
This was working but I'm now getting to a point where I need to modify the body template and add further logic to the <Column>
props. This in turn will lead to a fairly convoluted and repetitive code base for a simple job.
MyDataTableComponent.vue
<!-- DataTable tag omitted for brevity -->
<Column
v-for="col of columns"
:field="col.field"
:header="col.header"
:key="col.field"
:showFilterMatchModes="showFilterMatchModes(col)"
:showFilterOperator="showFilterMatchModes(col)"
:maxConstraints="col.maxConstraints ?? 2"
style="min-width: 14rem"
dataType="col.type"
>
<!-- soon there will be more logic regarding whether to use the body template etc -->
<template v-if="col.filter" #filter="{ filterModel }">
<!-- essentially wrappers around the form element of a filter menu -->
<StringFilter
v-if="col.type === 'string'"
:filterModel="filterModel"
@update:filterModel="
(newValue) => (filterModel.value = newValue)
"
:placeholder="col.placeholder"
/>
<SelectFilter
v-else-if="col.type === 'select'"
:filterModel="filterModel"
@update:filterModel="
(newValue) => (filterModel.value = newValue)
"
:placeholder="col.placeholder"
:options="col.options"
/>
<!-- more filters and v-if-elses -->
<div v-else>Nothing to see here...</div>
</template>
</Column>
What I'm trying to do instead is:
SelectColumn.vue (one column wrapper component per column type)
<script setup>...</script>
<template>
<Column
:field="col.field"
:header="col.header"
:showFilterMatchModes="false"
:showFilterOperator="false"
:filterMenuStyle="{ width: '14rem' }"
:maxConstraints="1"
>
<template v-if="col.filter" #filter="{ filterModel }">
<SelectFilter
v-if="col.type === 'string'"
:filterModel="filterModel"
@update:filterModel="
(newValue) => (filterModel.value = newValue)
"
:placeholder="col.placeholder"
/>
</template>
</Column>
</template>
MyDataTableComponent.vue
<!-- DataTable tag omitted for brevity -->
<component
v-for="col of columns"
:key="col.field"
:is="col.columnType"
v-bind="{ col: col }" <!-- I'm assuming that I need to bind some data/props from the table and listen to some events here -->
/>
I have also tried binding $attrs
and the composition version with useAttrs
but there doesn't seem to be anything picked up (just { _vInternal: 1 }
).
I hope that makes sense.
If you could point me in the right direction, I'd be really appreciative.
I've just come across issue 1356.
If this is still the case, it's a strange implementation choice.
How difficult would it be to break out columns into standalone (non-kind-of-helper) components?
I feel like the the use-case speaks for itself in the fact that you have a very powerful data-table component that seems like it conforms to Vue best practices. But when devs want to organise their own code as logical and reusable SOLID components it falls down because one of the main components of it aren't actually components?
Could somebody please get back to me with any information regarding how to achieve this?
Does anybody have any insights into this yet?
We had the same problem, but we managed to find a workaround of exporting out wrapper component with the name Column
.
Would be nice to have support for column wrapping, having to write out all the body, header, filter and loading templates in every table creates a lot of boilerplate code.
We had the same problem, but we managed to find a workaround of exporting out wrapper component with the name
Column
. Would be nice to have support for column wrapping, having to write out all the body, header, filter and loading templates in every table creates a lot of boilerplate code.
@Muchiachio Hello, do you have an example of what you have done 😄
Datatable has these lines, which check the component name. That's why if you name your component Column
it will be correctly included as a child.
It looks similar to this.
<script>
export default {
name: "Column"
}
</script>
This alone however won't include props, so if you use some of them you will have to include them the same way it's done in default column implementation.
Issue tracker is used for defects only as part of our commitment to quality and continuous improvement in all areas. Enhancements are collected as valuable community feedback and managed internally so moving this enhancement ticket to our internal project management backlog.