Fixed row filtering

pull/1021/head
Cagatay Civici 2021-02-17 00:52:57 +03:00
parent 24a0c7aaa7
commit d15eaff431
5 changed files with 283 additions and 325 deletions

View File

@ -212,7 +212,7 @@ export default {
}, },
ariaSort() { ariaSort() {
if (this.columnProp('sortable')) { if (this.columnProp('sortable')) {
const sortIcon = this.getSortableColumnIcon(); const sortIcon = this.sortableColumnIcon;
if (sortIcon[1]['pi-sort-amount-down']) if (sortIcon[1]['pi-sort-amount-down'])
return 'descending'; return 'descending';
else if (sortIcon[1]['pi-sort-amount-up-alt']) else if (sortIcon[1]['pi-sort-amount-up-alt'])

View File

@ -9,18 +9,24 @@
:resizableColumns="resizableColumns" @column-resizestart="$emit('column-resizestart', $event)" :resizableColumns="resizableColumns" @column-resizestart="$emit('column-resizestart', $event)"
:sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta" :sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta"
:allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('column-change', $event)" :allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('column-change', $event)"
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :filters="filters" :filterDisplay="filterDisplay" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')"
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)" @operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)"
@constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/> @constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
</template> </template>
</tr> </tr>
<tr v-if="filterDisplay === 'row'" role="row"> <tr v-if="filterDisplay === 'row'" role="row">
<template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i"> <template v-for="(col,i) of columns" :key="columnProp(col, 'columnKey')||columnProp(col, 'field')||i">
<DTHeaderCell v-if="rowGroupMode !== 'subheader' || (groupRowsBy !== columnProp(col, 'field'))" :column="col" :filterColumn="true" <th :style="getFilterColumnHeaderStyle(col)" :class="getFilterColumnHeaderClass(col)">
:allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('checkbox-change', $event)" <DTColumnFilter v-if="col.children && col.children.filter" :field="columnProp(col,'filterField')||columnProp(col,'field')" :type="columnProp(col,'dataType')" display="row"
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :showMenu="columnProp(col,'showFilterMenu')" :filterElement="col.children && col.children.filter"
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)" :filterHeaderTemplate="col.children && col.children.filterheader" :filterFooterTemplate="col.children && col.children.filterfooter"
@constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/> :filterClearTemplate="col.children && col.children.filterclear" :filterApplyTemplate="col.children && col.children.filterapply"
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :filterMenuStyle="columnProp(col,'filterMenuStyle')" :filterMenuClass="columnProp(col,'filterMenuClass')"
:showOperator="columnProp(col,'showFilterOperator')" :showClearButton="columnProp(col,'showClearButton')" :showApplyButton="columnProp(col,'showApplyButton')"
:showMatchModes="columnProp(col,'showFilterMatchModes')" :showAddButton="columnProp(col,'showAddButton')" :matchModeOptions="columnProp(col,'filterMatchModeOptions')" :maxConstraints="columnProp(col,'maxConstraints')"
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)"
@constraint-add="$emit('constraint-add', $event)" @constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
</th>
</template> </template>
</tr> </tr>
</template> </template>
@ -31,7 +37,7 @@
@column-click="$emit('column-click', $event)" @column-mousedown="$emit('column-mousedown', $event)" @column-click="$emit('column-click', $event)" @column-mousedown="$emit('column-mousedown', $event)"
:sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta" :sortMode="sortMode" :sortField="sortField" :sortOrder="sortOrder" :multiSortMeta="multiSortMeta"
:allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('column-change', $event)" :allRowsSelected="allRowsSelected" :empty="empty" @checkbox-change="$emit('column-change', $event)"
:filters="filters" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')" :filters="filters" :filterDisplay="filterDisplay" :filtersStore="filtersStore" @filter-change="$emit('filter-change', $event)" @filter-apply="$emit('filter-apply')"
@operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)" @operator-change="$emit('operator-change',$event)" @matchmode-change="$emit('matchmode-change', $event)" @constraint-add="$emit('constraint-add', $event)"
@constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/> @constraint-remove="$emit('constraint-remove', $event)" @apply-click="$emit('apply-click',$event)"/>
</template> </template>
@ -42,6 +48,7 @@
<script> <script>
import HeaderCell from './HeaderCell'; import HeaderCell from './HeaderCell';
import ColumnFilter from './ColumnFilter';
export default { export default {
emits: ['column-click', 'column-mousedown', 'column-dragstart', 'column-dragover', 'column-dragleave', 'column-drop', emits: ['column-click', 'column-mousedown', 'column-dragstart', 'column-dragover', 'column-dragleave', 'column-drop',
@ -110,11 +117,15 @@ export default {
return col.props ? ((col.type.props[prop].type === Boolean && col.props[prop] === '') ? true : col.props[prop]) : null; return col.props ? ((col.type.props[prop].type === Boolean && col.props[prop] === '') ? true : col.props[prop]) : null;
}, },
getFilterColumnHeaderClass(column) { getFilterColumnHeaderClass(column) {
return ['p-filter-column', this.columnProp(column, 'filterHeaderClass')]; return ['p-filter-column', this.columnProp(column, 'filterHeaderClass'), this.columnProp(column, 'class')];
},
getFilterColumnHeaderStyle(column) {
return [this.columnProp(column, 'filterHeaderStyle'), this.columnProp(column, 'style')];
} }
}, },
components: { components: {
'DTHeaderCell': HeaderCell 'DTHeaderCell': HeaderCell,
'DTColumnFilter': ColumnFilter
} }
} }
</script> </script>

View File

@ -10,17 +10,18 @@
<div class="content-section implementation"> <div class="content-section implementation">
<div class="card"> <div class="card">
<DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10" <DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10"
dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" :filters="filters" :loading="loading" dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" v-model:filters="filters" filterDisplay="menu" :loading="loading"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]" paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
:globalFilterFields="['name','country.name','representative.name','status']">
<template #header> <template #header>
<div class="table-header"> <div class="p-d-flex p-jc-between">
List of Customers <h5 class="p-m-0">Customers</h5>
<span class="p-input-icon-left"> <span class="p-input-icon-left">
<i class="pi pi-search" /> <i class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Global Search" /> <InputText v-model="filters['global'].value" placeholder="Keyword Search" />
</span> </span>
</div> </div>
</template> </template>
<template #empty> <template #empty>
No customers found. No customers found.
@ -28,34 +29,35 @@
<template #loading> <template #loading>
Loading customers data. Please wait. Loading customers data. Please wait.
</template> </template>
<Column selectionMode="multiple" headerStyle="width: 3em"></Column> <Column selectionMode="multiple" headerStyle="width: 3rem"></Column>
<Column field="name" header="Name" :sortable="true"> <Column field="name" header="Name" sortable>
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Name</span> <span class="p-column-title">Name</span>
{{slotProps.data.name}} {{data.name}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['name']" class="p-column-filter" placeholder="Search by name"/> <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by name"/>
</template> </template>
</Column> </Column>
<Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains"> <Column field="country.name" header="Country" sortable filterMatchMode="contains">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Country</span> <span class="p-column-title">Country</span>
<img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + slotProps.data.country.code" width="30" /> <img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + data.country.code" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span> <span class="image-text">{{data.country.name}}</span>
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['country.name']" class="p-column-filter" placeholder="Search by country"/> <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by country"/>
</template> </template>
</Column> </Column>
<Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in"> <Column header="Representative" sortable sortField="representative.name" :showFilterMatchModes="false" :filterMenuStyle="{'width':'14rem'}">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Representative</span> <span class="p-column-title">Agent</span>
<img :alt="slotProps.data.representative.name" :src="'demo/images/avatar/' + slotProps.data.representative.image" width="32" style="vertical-align: middle" /> <img :alt="data.representative.name" :src="'demo/images/avatar/' + data.representative.image" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span> <span class="image-text">{{data.representative.name}}</span>
</template> </template>
<template #filter> <template #filter="{filterModel}">
<MultiSelect v-model="filters['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter"> <div class="p-mb-3 p-text-bold">Agent Picker</div>
<MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name" placeholder="Any" class="p-column-filter">
<template #option="slotProps"> <template #option="slotProps">
<div class="p-multiselect-representative-option"> <div class="p-multiselect-representative-option">
<img :alt="slotProps.option.name" :src="'demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" /> <img :alt="slotProps.option.name" :src="'demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" />
@ -65,40 +67,56 @@
</MultiSelect> </MultiSelect>
</template> </template>
</Column> </Column>
<Column field="date" header="Date" :sortable="true" filterMatchMode="custom" :filterFunction="filterDate"> <Column field="date" header="Date" sortable dataType="date">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Date</span> <span class="p-column-title">Date</span>
<span>{{slotProps.data.date}}</span> {{formatDate(data.date)}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<Calendar v-model="filters['date']" dateFormat="yy-mm-dd" class="p-column-filter" placeholder="Registration Date"/> <Calendar v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" />
</template> </template>
</Column> </Column>
<Column field="status" header="Status" :sortable="true" filterMatchMode="equals"> <Column field="balance" header="Balance" sortable dataType="numeric">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Status</span> <span class="p-column-title">Balance</span>
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span> {{formatCurrency(data.balance)}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<Dropdown v-model="filters['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true"> <InputNumber v-model="filterModel.value" mode="currency" currency="USD" locale="en-US" />
</template>
</Column>
<Column field="status" header="Status" sortable :filterMenuStyle="{'width':'14rem'}">
<template #body="{data}">
<span class="p-column-title">Status</span>
<span :class="'customer-badge status-' + data.status">{{data.status}}</span>
</template>
<template #filter="{filterModel}">
<Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true">
<template #value="slotProps">
<span :class="'customer-badge status-' + slotProps.value">{{slotProps.value}}</span>
</template>
<template #option="slotProps"> <template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span> <span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
</Column> </Column>
<Column field="activity" header="Activity" :sortable="true" filterMatchMode="gte"> <Column field="activity" header="Activity" sortable :showFilterMatchModes="false">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Activity</span> <span class="p-column-title">Activity</span>
<ProgressBar :value="slotProps.data.activity" :showValue="false" /> <ProgressBar :value="data.activity" :showValue="false" />
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['activity']" class="p-column-filter" placeholder="Minimum"/> <Slider v-model="filterModel.value" range class="p-m-3"></Slider>
<div class="p-d-flex p-ai-center p-jc-between p-px-2">
<span>{{filterModel.value ? filterModel.value[0] : 0}}</span>
<span>{{filterModel.value ? filterModel.value[1] : 100}}</span>
</div>
</template> </template>
</Column> </Column>
<Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible"> <Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<template #body> <template #body>
<Button type="button" icon="pi pi-cog" class="p-button-secondary"></Button> <Button type="button" icon="pi pi-cog"></Button>
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@ -111,6 +129,7 @@
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import {FilterMatchMode,FilterOperator} from 'primevue/api';
import DataTableDoc from './DataTableDoc'; import DataTableDoc from './DataTableDoc';
export default { export default {
@ -118,7 +137,17 @@ export default {
return { return {
customers: null, customers: null,
selectedCustomers: null, selectedCustomers: null,
filters: {}, filters: {
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
'name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'country.name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'representative': {value: null, matchMode: FilterMatchMode.IN},
'date': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.DATE_IS}]},
'balance': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'status': {operator: FilterOperator.OR, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'activity': {value: null, matchMode: FilterMatchMode.BETWEEN},
'verified': {value: null, matchMode: FilterMatchMode.EQUALS}
},
loading: true, loading: true,
representatives: [ representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'}, {name: "Amy Elsner", image: 'amyelsner.png'},
@ -141,34 +170,22 @@ export default {
this.customerService = new CustomerService(); this.customerService = new CustomerService();
}, },
mounted() { mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data); this.customerService.getCustomersLarge().then(data => {
this.loading = false; this.customers = data;
this.customers.forEach(customer => customer.date = new Date(customer.date));
this.loading = false;
});
}, },
methods: { methods: {
filterDate(value, filter) { formatDate(value) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { return value.toLocaleDateString('en-US', {
return true; day: '2-digit',
} month: '2-digit',
year: 'numeric',
if (value === undefined || value === null) { });
return false;
}
return value === this.formatDate(filter);
}, },
formatDate(date) { formatCurrency(value) {
let month = date.getMonth() + 1; return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
let day = date.getDate();
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
} }
}, },
components: { components: {
@ -193,11 +210,6 @@ export default {
} }
} }
.table-header {
display: flex;
justify-content: space-between;
}
::v-deep(.p-datepicker) { ::v-deep(.p-datepicker) {
min-width: 25rem; min-width: 25rem;

View File

@ -2520,17 +2520,18 @@ export default {
<pre v-code><code><template v-pre> <pre v-code><code><template v-pre>
&lt;DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10" &lt;DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10"
dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" :filters="filters" :loading="loading" dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" v-model:filters="filters" filterDisplay="menu" :loading="loading"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]" paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"&gt; currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
:globalFilterFields="['name','country.name','representative.name','status']"&gt;
&lt;template #header&gt; &lt;template #header&gt;
&lt;div class="table-header"&gt; &lt;div class="p-d-flex p-jc-between"&gt;
List of Customers &lt;h5 class="p-m-0"&gt;Customers&lt;/h5&gt;
&lt;span class="p-input-icon-left"&gt; &lt;span class="p-input-icon-left"&gt;
&lt;i class="pi pi-search" /&gt; &lt;i class="pi pi-search" /&gt;
&lt;InputText v-model="filters['global']" placeholder="Global Search" /&gt; &lt;InputText v-model="filters['global'].value" placeholder="Keyword Search" /&gt;
&lt;/span&gt; &lt;/span&gt;
&lt;/div&gt; &lt;/div&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #empty&gt; &lt;template #empty&gt;
No customers found. No customers found.
@ -2538,34 +2539,35 @@ export default {
&lt;template #loading&gt; &lt;template #loading&gt;
Loading customers data. Please wait. Loading customers data. Please wait.
&lt;/template&gt; &lt;/template&gt;
&lt;Column selectionMode="multiple" headerStyle="width: 3em"&gt;&lt;/Column&gt; &lt;Column selectionMode="multiple" headerStyle="width: 3rem"&gt;&lt;/Column&gt;
&lt;Column field="name" header="Name" :sortable="true"&gt; &lt;Column field="name" header="Name" sortable&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Name&lt;/span&gt; &lt;span class="p-column-title"&gt;Name&lt;/span&gt;
{{slotProps.data.name}} {{data.name}}
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;InputText type="text" v-model="filters['name']" class="p-column-filter" placeholder="Search by name"/&gt; &lt;InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by name"/&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains"&gt; &lt;Column field="country.name" header="Country" sortable filterMatchMode="contains"&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Country&lt;/span&gt; &lt;span class="p-column-title"&gt;Country&lt;/span&gt;
&lt;img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + slotProps.data.country.code" width="30" /&gt; &lt;img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + data.country.code" width="30" /&gt;
&lt;span class="image-text"&gt;{{slotProps.data.country.name}}&lt;/span&gt; &lt;span class="image-text"&gt;{{data.country.name}}&lt;/span&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;InputText type="text" v-model="filters['country.name']" class="p-column-filter" placeholder="Search by country"/&gt; &lt;InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by country"/&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in"&gt; &lt;Column header="Representative" sortable sortField="representative.name" :showFilterMatchModes="false" :filterMenuStyle="{'width':'14rem'}"&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Representative&lt;/span&gt; &lt;span class="p-column-title"&gt;Agent&lt;/span&gt;
&lt;img :alt="slotProps.data.representative.name" :src="'demo/images/avatar/' + slotProps.data.representative.image" width="32" style="vertical-align: middle" /&gt; &lt;img :alt="data.representative.name" :src="'demo/images/avatar/' + data.representative.image" width="32" style="vertical-align: middle" /&gt;
&lt;span class="image-text"&gt;{{slotProps.data.representative.name}}&lt;/span&gt; &lt;span class="image-text"&gt;{{data.representative.name}}&lt;/span&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;MultiSelect v-model="filters['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter"&gt; &lt;div class="p-mb-3 p-text-bold"&gt;Agent Picker&lt;/div&gt;
&lt;MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name" placeholder="Any" class="p-column-filter"&gt;
&lt;template #option="slotProps"&gt; &lt;template #option="slotProps"&gt;
&lt;div class="p-multiselect-representative-option"&gt; &lt;div class="p-multiselect-representative-option"&gt;
&lt;img :alt="slotProps.option.name" :src="'demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" /&gt; &lt;img :alt="slotProps.option.name" :src="'demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" /&gt;
@ -2575,40 +2577,56 @@ export default {
&lt;/MultiSelect&gt; &lt;/MultiSelect&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="date" header="Date" :sortable="true" filterMatchMode="custom" :filterFunction="filterDate"&gt; &lt;Column field="date" header="Date" sortable dataType="date"&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Date&lt;/span&gt; &lt;span class="p-column-title"&gt;Date&lt;/span&gt;
&lt;span&gt;{{slotProps.data.date}}&lt;/span&gt; {{formatDate(data.date)}}
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;Calendar v-model="filters['date']" dateFormat="yy-mm-dd" class="p-column-filter" placeholder="Registration Date"/&gt; &lt;Calendar v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" /&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="status" header="Status" :sortable="true" filterMatchMode="equals"&gt; &lt;Column field="balance" header="Balance" sortable dataType="numeric"&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Status&lt;/span&gt; &lt;span class="p-column-title"&gt;Balance&lt;/span&gt;
&lt;span :class="'customer-badge status-' + slotProps.data.status"&gt;{{slotProps.data.status}}&lt;/span&gt; {{formatCurrency(data.balance)}}
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;Dropdown v-model="filters['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true"&gt; &lt;InputNumber v-model="filterModel.value" mode="currency" currency="USD" locale="en-US" /&gt;
&lt;/template&gt;
&lt;/Column&gt;
&lt;Column field="status" header="Status" sortable :filterMenuStyle="{'width':'14rem'}"&gt;
&lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Status&lt;/span&gt;
&lt;span :class="'customer-badge status-' + data.status"&gt;{{data.status}}&lt;/span&gt;
&lt;/template&gt;
&lt;template #filter="{filterModel}"&gt;
&lt;Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"&gt;
&lt;template #value="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.value"&gt;{{slotProps.value}}&lt;/span&gt;
&lt;/template&gt;
&lt;template #option="slotProps"&gt; &lt;template #option="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt; &lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Dropdown&gt; &lt;/Dropdown&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="activity" header="Activity" :sortable="true" filterMatchMode="gte"&gt; &lt;Column field="activity" header="Activity" sortable :showFilterMatchModes="false"&gt;
&lt;template #body="slotProps"&gt; &lt;template #body="{data}"&gt;
&lt;span class="p-column-title"&gt;Activity&lt;/span&gt; &lt;span class="p-column-title"&gt;Activity&lt;/span&gt;
&lt;ProgressBar :value="slotProps.data.activity" :showValue="false" /&gt; &lt;ProgressBar :value="data.activity" :showValue="false" /&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #filter&gt; &lt;template #filter="{filterModel}"&gt;
&lt;InputText type="text" v-model="filters['activity']" class="p-column-filter" placeholder="Minimum"/&gt; &lt;Slider v-model="filterModel.value" range class="p-m-3"&gt;&lt;/Slider&gt;
&lt;div class="p-d-flex p-ai-center p-jc-between p-px-2"&gt;
&lt;span&gt;{{filterModel.value ? filterModel.value[0] : 0}}&lt;/span&gt;
&lt;span&gt;{{filterModel.value ? filterModel.value[1] : 100}}&lt;/span&gt;
&lt;/div&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible"&gt; &lt;Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible"&gt;
&lt;template #body&gt; &lt;template #body&gt;
&lt;Button type="button" icon="pi pi-cog" class="p-button-secondary"&gt;&lt;/Button&gt; &lt;Button type="button" icon="pi pi-cog"&gt;&lt;/Button&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
@ -2617,13 +2635,24 @@ export default {
<pre v-code.script><code> <pre v-code.script><code>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import {FilterMatchMode,FilterOperator} from 'primevue/api';
export default { export default {
data() { data() {
return { return {
customers: null, customers: null,
selectedCustomers: null, selectedCustomers: null,
filters: {}, filters: {
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
'name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'country.name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'representative': {value: null, matchMode: FilterMatchMode.IN},
'date': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.DATE_IS}]},
'balance': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'status': {operator: FilterOperator.OR, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'activity': {value: null, matchMode: FilterMatchMode.BETWEEN},
'verified': {value: null, matchMode: FilterMatchMode.EQUALS}
},
loading: true, loading: true,
representatives: [ representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'}, {name: "Amy Elsner", image: 'amyelsner.png'},
@ -2648,136 +2677,26 @@ export default {
mounted() { mounted() {
this.customerService.getCustomersLarge().then(data => { this.customerService.getCustomersLarge().then(data => {
this.customers = data; this.customers = data;
this.customers.forEach(customer => customer.date = new Date(customer.date));
this.loading = false; this.loading = false;
}); });
}, },
methods: { methods: {
filterDate(value, filter) { formatDate(value) {
if (filter === undefined || filter === null || (typeof filter === 'string' &amp;&amp; filter.trim() === '')) { return value.toLocaleDateString('en-US', {
return true; day: '2-digit',
} month: '2-digit',
year: 'numeric',
if (value === undefined || value === null) { });
return false;
}
return value === this.formatDate(filter);
}, },
formatDate(date) { formatCurrency(value) {
let month = date.getMonth() + 1; return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
let day = date.getDate();
if (month &lt; 10) {
month = '0' + month;
}
if (day &lt; 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
} }
} }
} }
</code></pre> </code></pre>
<pre v-code.css><code>
::v-deep(.p-paginator) {
.p-paginator-current {
margin-left: auto;
}
}
::v-deep(.p-progressbar) {
height: .5rem;
background-color: #D8DADC;
.p-progressbar-value {
background-color: #607D8B;
}
}
.table-header {
display: flex;
justify-content: space-between;
}
::v-deep(.p-datepicker) {
min-width: 25rem;
td {
font-weight: 400;
}
}
::v-deep(.p-datatable.p-datatable-customers) {
.p-datatable-header {
padding: 1rem;
text-align: left;
font-size: 1.5rem;
}
.p-paginator {
padding: 1rem;
}
.p-datatable-thead > tr > th {
text-align: left;
}
.p-datatable-tbody > tr > td {
cursor: auto;
}
.p-dropdown-label:not(.p-placeholder) {
text-transform: uppercase;
}
}
/* Responsive */
.p-datatable-customers .p-datatable-tbody > tr > td .p-column-title {
display: none;
}
@media screen and (max-width: 960px) {
::v-deep(.p-datatable) {
&.p-datatable-customers {
.p-datatable-thead > tr > th,
.p-datatable-tfoot > tr > td {
display: none !important;
}
.p-datatable-tbody > tr {
border-bottom: 1px solid var(--layer-2);
> td {
text-align: left;
display: block;
border: 0 none !important;
width: 100% !important;
float: left;
clear: left;
border: 0 none;
.p-column-title {
padding: .4rem;
min-width: 30%;
display: inline-block;
margin: -.4rem 1rem -.4rem -.4rem;
font-weight: bold;
}
.p-progressbar {
margin-top: .5rem;
}
}
}
}
}
}
</code></pre>
</TabPanel> </TabPanel>
</TabView> </TabView>
</div> </div>
@ -2795,17 +2714,18 @@ export default {
<div class="content-section implementation"> <div class="content-section implementation">
<div class="card"> <div class="card">
<DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10" <DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10"
dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" :filters="filters" :loading="loading" dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" v-model:filters="filters" filterDisplay="menu" :loading="loading"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]" paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"
:globalFilterFields="['name','country.name','representative.name','status']">
<template #header> <template #header>
<div class="table-header"> <div class="p-d-flex p-jc-between">
List of Customers <h5 class="p-m-0">Customers</h5>
<span class="p-input-icon-left"> <span class="p-input-icon-left">
<i class="pi pi-search" /> <i class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Global Search" /> <InputText v-model="filters['global'].value" placeholder="Keyword Search" />
</span> </span>
</div> </div>
</template> </template>
<template #empty> <template #empty>
No customers found. No customers found.
@ -2813,77 +2733,94 @@ export default {
<template #loading> <template #loading>
Loading customers data. Please wait. Loading customers data. Please wait.
</template> </template>
<Column selectionMode="multiple" headerStyle="width: 3em"></Column> <Column selectionMode="multiple" headerStyle="width: 3rem"></Column>
<Column field="name" header="Name" :sortable="true"> <Column field="name" header="Name" sortable>
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Name</span> <span class="p-column-title">Name</span>
{{slotProps.data.name}} {{data.name}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['name']" class="p-column-filter" placeholder="Search by name"/> <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by name"/>
</template> </template>
</Column> </Column>
<Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains"> <Column field="country.name" header="Country" sortable filterMatchMode="contains">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Country</span> <span class="p-column-title">Country</span>
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="30" /> <img src="../../assets/images/flag_placeholder.png" :class="'flag flag-' + data.country.code" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span> <span class="image-text">{{data.country.name}}</span>
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['country.name']" class="p-column-filter" placeholder="Search by country"/> <InputText type="text" v-model="filterModel.value" class="p-column-filter" placeholder="Search by country"/>
</template> </template>
</Column> </Column>
<Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in"> <Column header="Representative" sortable sortField="representative.name" :showFilterMatchModes="false" :filterMenuStyle="{'width':'14rem'}">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Representative</span> <span class="p-column-title">Agent</span>
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" /> <img :alt="data.representative.name" :src="'demo/images/avatar/' + data.representative.image" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span> <span class="image-text">{{data.representative.name}}</span>
</template> </template>
<template #filter> <template #filter="{filterModel}">
<MultiSelect v-model="filters['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter"> <div class="p-mb-3 p-text-bold">Agent Picker</div>
<MultiSelect v-model="filterModel.value" :options="representatives" optionLabel="name" placeholder="Any" class="p-column-filter">
<template #option="slotProps"> <template #option="slotProps">
<div class="p-multiselect-representative-option"> <div class="p-multiselect-representative-option">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" /> <img :alt="slotProps.option.name" :src="'demo/images/avatar/' + slotProps.option.image" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.option.name}}</span> <span class="image-text">{{slotProps.option.name}}</span>
</div> </div>
</template> </template>
</MultiSelect> </MultiSelect>
</template> </template>
</Column> </Column>
<Column field="date" header="Date" :sortable="true" filterMatchMode="custom" :filterFunction="filterDate"> <Column field="date" header="Date" sortable dataType="date">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Date</span> <span class="p-column-title">Date</span>
<span>{{slotProps.data.date}}</span> {{formatDate(data.date)}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<Calendar v-model="filters['date']" dateFormat="yy-mm-dd" class="p-column-filter" placeholder="Registration Date"/> <Calendar v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" />
</template> </template>
</Column> </Column>
<Column field="status" header="Status" :sortable="true" filterMatchMode="equals"> <Column field="balance" header="Balance" sortable dataType="numeric">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Status</span> <span class="p-column-title">Balance</span>
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span> {{formatCurrency(data.balance)}}
</template> </template>
<template #filter> <template #filter="{filterModel}">
<Dropdown v-model="filters['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true"> <InputNumber v-model="filterModel.value" mode="currency" currency="USD" locale="en-US" />
</template>
</Column>
<Column field="status" header="Status" sortable :filterMenuStyle="{'width':'14rem'}">
<template #body="{data}">
<span class="p-column-title">Status</span>
<span :class="'customer-badge status-' + data.status">{{data.status}}</span>
</template>
<template #filter="{filterModel}">
<Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true">
<template #value="slotProps">
<span :class="'customer-badge status-' + slotProps.value">{{slotProps.value}}</span>
</template>
<template #option="slotProps"> <template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span> <span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template> </template>
</Dropdown> </Dropdown>
</template> </template>
</Column> </Column>
<Column field="activity" header="Activity" :sortable="true" filterMatchMode="gte"> <Column field="activity" header="Activity" sortable :showFilterMatchModes="false">
<template #body="slotProps"> <template #body="{data}">
<span class="p-column-title">Activity</span> <span class="p-column-title">Activity</span>
<ProgressBar :value="slotProps.data.activity" :showValue="false" /> <ProgressBar :value="data.activity" :showValue="false" />
</template> </template>
<template #filter> <template #filter="{filterModel}">
<InputText type="text" v-model="filters['activity']" class="p-column-filter" placeholder="Minimum"/> <Slider v-model="filterModel.value" range class="p-m-3"></Slider>
<div class="p-d-flex p-ai-center p-jc-between p-px-2">
<span>{{filterModel.value ? filterModel.value[0] : 0}}</span>
<span>{{filterModel.value ? filterModel.value[1] : 100}}</span>
</div>
</template> </template>
</Column> </Column>
<Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible"> <Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<template #body> <template #body>
<Button type="button" icon="pi pi-cog" class="p-button-secondary"></Button> <Button type="button" icon="pi pi-cog"></Button>
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@ -2893,14 +2830,25 @@ export default {
</template> </template>
<script> <script>
import CustomerService from '../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import {FilterMatchMode,FilterOperator} from 'primevue/api';
export default { export default {
data() { data() {
return { return {
customers: null, customers: null,
selectedCustomers: null, selectedCustomers: null,
filters: {}, filters: {
'global': {value: null, matchMode: FilterMatchMode.CONTAINS},
'name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'country.name': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.STARTS_WITH}]},
'representative': {value: null, matchMode: FilterMatchMode.IN},
'date': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.DATE_IS}]},
'balance': {operator: FilterOperator.AND, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'status': {operator: FilterOperator.OR, constraints: [{value: null, matchMode: FilterMatchMode.EQUALS}]},
'activity': {value: null, matchMode: FilterMatchMode.BETWEEN},
'verified': {value: null, matchMode: FilterMatchMode.EQUALS}
},
loading: true, loading: true,
representatives: [ representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'}, {name: "Amy Elsner", image: 'amyelsner.png'},
@ -2923,34 +2871,22 @@ export default {
this.customerService = new CustomerService(); this.customerService = new CustomerService();
}, },
mounted() { mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data); this.customerService.getCustomersLarge().then(data => {
this.loading = false; this.customers = data;
this.customers.forEach(customer => customer.date = new Date(customer.date));
this.loading = false;
});
}, },
methods: { methods: {
filterDate(value, filter) { formatDate(value) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) { return value.toLocaleDateString('en-US', {
return true; day: '2-digit',
} month: '2-digit',
year: 'numeric',
if (value === undefined || value === null) { });
return false;
}
return value === this.formatDate(filter);
}, },
formatDate(date) { formatCurrency(value) {
let month = date.getMonth() + 1; return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
let day = date.getDate();
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
} }
} }
}`, }`,
@ -2970,11 +2906,6 @@ export default {
} }
} }
.table-header {
display: flex;
justify-content: space-between;
}
::v-deep(.p-datepicker) { ::v-deep(.p-datepicker) {
min-width: 25rem; min-width: 25rem;

View File

@ -101,7 +101,8 @@
<template #filter="{filterModel}"> <template #filter="{filterModel}">
<Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"> <Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true">
<template #value="slotProps"> <template #value="slotProps">
<span :class="'customer-badge status-' + slotProps.value">{{slotProps.value}}</span> <span :class="'customer-badge status-' + slotProps.value" v-if="slotProps.value">{{slotProps.value}}</span>
<span v-else>{{slotProps.placeholder}}</span>
</template> </template>
<template #option="slotProps"> <template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span> <span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
@ -198,7 +199,8 @@
<template #filter="{filterModel,filterCallback}"> <template #filter="{filterModel,filterCallback}">
<Dropdown v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"> <Dropdown v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true">
<template #value="slotProps"> <template #value="slotProps">
<span :class="'customer-badge status-' + slotProps.value">{{slotProps.value}}</span> <span :class="'customer-badge status-' + slotProps.value" v-if="slotProps.value">{{slotProps.value}}</span>
<span v-else>{{slotProps.placeholder}}</span>
</template> </template>
<template #option="slotProps"> <template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span> <span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
@ -316,7 +318,8 @@
&lt;template #filter="{filterModel}"&gt; &lt;template #filter="{filterModel}"&gt;
&lt;Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"&gt; &lt;Dropdown v-model="filterModel.value" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"&gt;
&lt;template #value="slotProps"&gt; &lt;template #value="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.value"&gt;{{slotProps.value}}&lt;/span&gt; &lt;span :class="'customer-badge status-' + slotProps.value" v-if="slotProps.value"&gt;{{slotProps.value}}&lt;/span&gt;
&lt;span v-else&gt;{{slotProps.placeholder}}&lt;/span&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #option="slotProps"&gt; &lt;template #option="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt; &lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt;
@ -413,7 +416,8 @@
&lt;template #filter="{filterModel,filterCallback}"&gt; &lt;template #filter="{filterModel,filterCallback}"&gt;
&lt;Dropdown v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"&gt; &lt;Dropdown v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Any" class="p-column-filter" :showClear="true"&gt;
&lt;template #value="slotProps"&gt; &lt;template #value="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.value"&gt;{{slotProps.value}}&lt;/span&gt; &lt;span :class="'customer-badge status-' + slotProps.value" v-if="slotProps.value"&gt;{{slotProps.value}}&lt;/span&gt;
&lt;span v-else&gt;{{slotProps.placeholder}}&lt;/span&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;template #option="slotProps"&gt; &lt;template #option="slotProps"&gt;
&lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt; &lt;span :class="'customer-badge status-' + slotProps.option"&gt;{{slotProps.option}}&lt;/span&gt;