Custom Filter Row Not Working

UI Components for Vue
Post Reply
TrojeENV
Posts: 5
Joined: 24 Aug 2023, 21:30

24 Aug 2023, 21:38

I am currently using the PrimeVue DataTable component in my app and up until now I've been using a custom filter row between the header row and the data rows to handle filtering.

It's been working great so far and produces the filter row. I upgraded to Laravel 10, did not touch the Vue or Datatable code at all (or the data being passed to it) and now all of a sudden the filter row is missing. It's not even in the DOM after the page loads (so not hidden either). I'm not sure why it doesn't display anymore. There are no errors in the console. The API response comes back fine and the data and headers in the DataTable populate perfectly. I'm just missing the column filters.

Anyone experience this before? Any ideas on what to try? I am completely blind as there are no errors anywhere yet it doesn't show the #filter row.

Code: Select all

<DataTable
	:value="tableData"
	:alwaysShowPaginator="alwaysShowPaginator"
	:paginator="paginator"
	:lazy="true"
	:loading="loading"
	:rows="rows"
	:totalRecords="totalRecords"
	:sortField="sort.sortBy"
	:sortOrder="sort.sortDir"
	ref="dt"
	dataKey="id"
	class="p-datatable"
	paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink"
	currentPageReportTemplate="Showing {first} to {last} of {totalRecords}"
	@page="onPage($event)"
	@sort="onSort($event)"
	responsiveLayout="scroll"
	:stripedRows="true"
>
                    <template #empty>
                        <div class="text-center">No matching records found.</div>
                    </template>
                    <template #loading>
                        <div class="text-center">Loading data. Please wait.</div>
                    </template>

                    <Column v-if="hasBefore" bodyStyle="text-align:left" :style="beforeSlotStyle" :headerStyle="beforeSlotStyle">
                        <template #body="slotProps">
                            <slot name="before" :slotProps="slotProps"></slot>
                        </template>
                    </Column>
                    <Column
                        v-for="col of columns"
                        :field="col.field"
                        :header="col.header"
                        :key="col.field"
                        :headerStyle="col.style"
                        :sortable="col.sortable"
                        :style="col.style"
                    >
                        <template #filter>
                            <InputText
                                type="text"
                                v-if="col.filter === 'text'"
                                v-model="filters[col.field]"
                                class="p-column-filter"
                                placeholder="Search..."
                                @keyup="onFilter"
                            />
                            <Dropdown
                                v-if="col.filter === 'select'"
                                v-model="filters[col.field]"
                                :options="col.options"
                                :showClear="true"
                                placeholder="Select..."
                                optionLabel="label"
                                optionValue="id"
                                @change="onSelect($event)"
                            >
                            </Dropdown>
                        </template>

                        <template #body="slotProps">
                            <span v-if="col.class" :class="col.class + ` bg-status-` + slotProps.data[col.field].replace(/\s+/g, '-').toLowerCase()">
                                <template v-if="col.currency">
                                    <template v-if="parseInt(slotProps.data[col.field])!==0">
                                        <div class="text-nowrap">
                                            {{ (slotProps.data['currency'] === 'usd') ? '$' + parseFloat(slotProps.data[col.field]).toFixed(2) : '£' + parseFloat(slotProps.data[col.field]).toFixed(2) }}
                                        </div>
                                    </template>
                                    <template v-else>--</template>
                                </template>
                                <template v-else>
                                    {{ slotProps.data[col.field] }}
                                </template>
                            </span>
                            <span v-else>
                                <template v-if="col.currency">
                                    <template v-if="parseInt(slotProps.data[col.field])!==0">
                                        <div class="text-nowrap">
                                            {{ (slotProps.data['currency'] === 'usd') ? '$' + parseFloat(slotProps.data[col.field]).toFixed(2) : '£' + parseFloat(slotProps.data[col.field]).toFixed(2) }}
                                        </div>
                                    </template>
                                    <template v-else>--</template>
                                </template>
                                <template v-else>
                                    {{ slotProps.data[col.field] }}
                                </template>
                            </span>
                            <span v-if="col.badge && slotProps.data.id === slotProps.data[col.badgeColumn]" :class="col.badgeClass">{{ col.badgeText }}</span>
                        </template>
                    </Column>
                    <Column v-if="hasAfter" bodyStyle="text-align:left" :style="afterSlotStyle" :headerStyle="afterSlotStyle">
                        <template #body="slotProps">
                            <slot name="after" :slotProps="slotProps"></slot>
                        </template>
                    </Column>
                    <template #paginatorLeft v-if="totalRecords">
                        <div class="p-l-sm">Showing {{ from }} to {{ to }} of {{ totalRecords }} records</div>
                    </template>
                </DataTable>
                

TrojeENV
Posts: 5
Joined: 24 Aug 2023, 21:30

25 Aug 2023, 15:45

After playing around with the code some more I do know that the input and dropdown are working and that its definitely tied to the #filter slot. I know this because I tried swapping out the slot name to a different positioned slot in the Column component and it worked. I changed it from #filter to #footer and then the filter row and inputs appeared at the bottom of the columns.

This mean the actual code within the slot is great. its just a matter of getting it into the right slot.

Does the #filter slot still exist in v2? or did it get renamed, replaced, or removed?

Thanks to anyone who can help!

tugce.kucukoglu
Posts: 560
Joined: 23 Oct 2020, 09:28

28 Aug 2023, 14:17

PrimeVue 2 supports #filter template.

But the issue is not clear. How can I replicate it?

TrojeENV
Posts: 5
Joined: 24 Aug 2023, 21:30

28 Aug 2023, 15:51

You basically create a datatable using the datatable component, then instead of using the built in filters, use the filter slot to pass in an input or dropdown primevue component into that slot so you can power a text filter (text input) or an option filter (dropdown). For me the filter slot never shows when I pass stuff into it. Regardless of what I pass it. I even tried just passing straight text into the #filter slot too and that doesn't work either.

TrojeENV
Posts: 5
Joined: 24 Aug 2023, 21:30

28 Aug 2023, 20:11

Ok, after digging some more I realized I'm not being accurate. I'm using the DataTable component but I'm having an issue with the Column component inside of the DataTable. In the past, I had a custom filter element below the column #header and above the column #body using a slot named #filter. It worked great, then all of a sudden stopped appearing. It's just the header and the body now. Below is more concise example of a column. I hope this helps make it more clear. Let me know if you have any additional questions or if anything is unclear.

If there is another way to get my input into the column below the header and above the body just let me know. I care more about the end result. I'm wondering if I should just include the filter input in the header below the header title.

Here is a more concise example:

Code: Select all

<Column
    field="deptCode"
    style="width: 54px; text-align: center"
    :sortable="false"
  >
    <template #header>
      <span title="Department"> Dept. </span>
    </template>
    
    <template #filter>
    	<input type="text" name="dept_name" />
    </template>

    <template #body="slotProps">
      <span :title="`${slotProps.data.deptName}`">{{
        slotProps.data.deptCode
      }}</span>
    </template>
  </Column>
  

TrojeENV
Posts: 5
Joined: 24 Aug 2023, 21:30

28 Aug 2023, 21:13

Ok, I think I might be on to something. There is a prop on the datatable component named "filterDisplay" and the valid values are "row" or "menu". When I set it to row the code works and the input appears but it has the DataTable filter icons to the right of it. I'm using CSS to hide them and it seems to be working. Just want to make sure this is the "best" way to resolve this. It seems to be working for the moment.

Post Reply

Return to “PrimeVue”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 14 guests