csb for datatable

pull/880/head
Tuğçe Küçükoğlu 2021-01-21 17:41:04 +03:00
parent 110f91631b
commit 3820b59857
26 changed files with 3053 additions and 8 deletions

View File

@ -21,6 +21,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small"/>
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products"&gt; &lt;DataTable :value="products"&gt;
@ -60,7 +63,29 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
return { return {
@ -74,5 +99,20 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -61,6 +61,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" :components="['ColumnGroup', 'Row', 'Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="sales"&gt; &lt;DataTable :value="sales"&gt;
@ -166,6 +169,70 @@ export default {
</div> </div>
</template> </template>
<script>
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
sales: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="sales">
<ColumnGroup type="header">
<Row>
<Column header="Product" :rowspan="3" />
<Column header="Sale Rate" :colspan="4" />
</Row>
<Row>
<Column header="Sales" :colspan="2" />
<Column header="Profits" :colspan="2" />
</Row>
<Row>
<Column header="Last Year" :sortable="true" field="lastYearSale"/>
<Column header="This Year" :sortable="true" field="thisYearSale"/>
<Column header="Last Year" :sortable="true" field="lastYearProfit"/>
<Column header="This Year" :sortable="true" field="thisYearProfit"/>
</Row>
</ColumnGroup>
<Column field="product" />
<Column field="lastYearSale">
<template #body="slotProps">
{{slotProps.data.lastYearSale}}%
</template>
</Column>
<Column field="thisYearSale">
<template #body="slotProps">
{{slotProps.data.thisYearSale}}%
</template>
</Column>
<Column field="lastYearProfit">
<template #body="slotProps">
{{formatCurrency(slotProps.data.lastYearProfit)}}
</template>
</Column>
<Column field="thisYearProfit">
<template #body="slotProps">
{{formatCurrency(slotProps.data.thisYearProfit)}}
</template>
</Column>
<ColumnGroup type="footer">
<Row>
<Column footer="Totals:" :colspan="3" footerStyle="text-align:right"/>
<Column :footer="lastYearTotal" />
<Column :footer="thisYearTotal" />
</Row>
</ColumnGroup>
</DataTable>
</div>
</div>
</div>
</template>
<script> <script>
export default { export default {
data() { data() {
@ -210,5 +277,50 @@ export default {
return this.formatCurrency(total); return this.formatCurrency(total);
} }
} }
}`
}
}
}
},
created() {
this.sales = [
{product: 'Bamboo Watch', lastYearSale: 51, thisYearSale: 40, lastYearProfit: 54406, thisYearProfit: 43342},
{product: 'Black Watch', lastYearSale: 83, thisYearSale: 9, lastYearProfit: 423132, thisYearProfit: 312122},
{product: 'Blue Band', lastYearSale: 38, thisYearSale: 5, lastYearProfit: 12321, thisYearProfit: 8500},
{product: 'Blue T-Shirt', lastYearSale: 49, thisYearSale: 22, lastYearProfit: 745232, thisYearProfit: 65323},
{product: 'Brown Purse', lastYearSale: 17, thisYearSale: 79, lastYearProfit: 643242, thisYearProfit: 500332},
{product: 'Chakra Bracelet', lastYearSale: 52, thisYearSale: 65, lastYearProfit: 421132, thisYearProfit: 150005},
{product: 'Galaxy Earrings', lastYearSale: 82, thisYearSale: 12, lastYearProfit: 131211, thisYearProfit: 100214},
{product: 'Game Controller', lastYearSale: 44, thisYearSale: 45, lastYearProfit: 66442, thisYearProfit: 53322},
{product: 'Gaming Set', lastYearSale: 90, thisYearSale: 56, lastYearProfit: 765442, thisYearProfit: 296232},
{product: 'Gold Phone Case', lastYearSale: 75, thisYearSale: 54, lastYearProfit: 21212, thisYearProfit: 12533}
];
},
methods: {
formatCurrency(value) {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
}
},
computed: {
lastYearTotal() {
let total = 0;
for(let sale of this.sales) {
total += sale.lastYearProfit;
}
return this.formatCurrency(total);
},
thisYearTotal() {
let total = 0;
for(let sale of this.sales) {
total += sale.thisYearProfit;
}
return this.formatCurrency(total);
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -33,6 +33,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;h3&gt;Fit Mode&lt;/h3&gt; &lt;h3&gt;Fit Mode&lt;/h3&gt;
@ -81,6 +84,42 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<h5>Fit Mode</h5>
<DataTable :value="products" :resizableColumns="true" columnResizeMode="fit" class="p-datatable-gridlines">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<h5>Expand Mode</h5>
<DataTable :value="products" :resizableColumns="true" columnResizeMode="expand" class="p-datatable-gridlines">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -95,5 +134,20 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -25,6 +25,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column', 'MultiSelect']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products"&gt; &lt;DataTable :value="products"&gt;
@ -82,6 +85,37 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
selectedColumns: null,
columns: null,
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products">
<template #header>
<div style="text-align:left">
<MultiSelect :modelValue="selectedColumns" :options="columns" optionLabel="header" @update:modelValue="onToggle"
placeholder="Select Columns" style="width: 20em"/>
</div>
</template>
<Column field="code" header="Code" />
<Column v-for="(col, index) of selectedColumns" :field="col.field" :header="col.header" :key="col.field + '_' + index"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -110,5 +144,32 @@ export default {
this.selectedColumns = this.columns.filter(col => value.includes(col)); this.selectedColumns = this.columns.filter(col => value.includes(col));
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
this.columns = [
{field: 'name', header: 'Name'},
{field: 'category', header: 'Category'},
{field: 'quantity', header: 'Quantity'}
];
this.selectedColumns = this.columns;
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
onToggle(value) {
this.selectedColumns = this.columns.filter(col => value.includes(col));
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -27,6 +27,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column', 'ContextMenu']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" contextMenu v-model:contextMenuSelection="selectedProduct" @row-contextmenu="onRowContextMenu"&gt; &lt;DataTable :value="products" contextMenu v-model:contextMenuSelection="selectedProduct" @row-contextmenu="onRowContextMenu"&gt;
@ -93,6 +96,43 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
selectedProduct: null,
menuModel: [
{label: 'View', icon: 'pi pi-fw pi-search', command: () => this.viewProduct(this.selectedProduct)},
{label: 'Delete', icon: 'pi pi-fw pi-times', command: () => this.deleteProduct(this.selectedProduct)}
],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<Toast />
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" contextMenu v-model:contextMenuSelection="selectedProduct" @row-contextmenu="onRowContextMenu">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="price" header="Price">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
</DataTable>
</div>
<ContextMenu :model="menuModel" ref="cm" />
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -128,5 +168,36 @@ export default {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'}); return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
onRowContextMenu(event) {
this.$refs.cm.show(event.originalEvent);
},
viewProduct(product) {
this.$toast.add({severity: 'info', summary: 'Product Selected', detail: product.name});
},
deleteProduct(product) {
this.products = this.products.filter((p) => p.id !== product.id);
this.$toast.add({severity: 'info', summary: 'Product Deleted', detail: product.name});
this.selectedProduct = null;
},
formatCurrency(value) {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -161,6 +161,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products" :components="['Column', 'Toolbar', 'Button', 'FileUpload', 'InputText', 'Rating', 'Dialog', 'RadioButton', 'Textarea', 'InputNumber', 'Dropdown']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -429,6 +432,7 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default { export default {
data() { data() {
@ -445,7 +449,184 @@ export default {
{label: 'INSTOCK', value: 'instock'}, {label: 'INSTOCK', value: 'instock'},
{label: 'LOWSTOCK', value: 'lowstock'}, {label: 'LOWSTOCK', value: 'lowstock'},
{label: 'OUTOFSTOCK', value: 'outofstock'} {label: 'OUTOFSTOCK', value: 'outofstock'}
] ],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<Toast />
<div class="content-section implementation">
<div class="card">
<Toolbar class="p-mb-4">
<template #left>
<Button label="New" icon="pi pi-plus" class="p-button-success p-mr-2" @click="openNew" />
<Button label="Delete" icon="pi pi-trash" class="p-button-danger" @click="confirmDeleteSelected" :disabled="!selectedProducts || !selectedProducts.length" />
</template>
<template #right>
<FileUpload mode="basic" accept="image/*" :maxFileSize="1000000" label="Import" chooseLabel="Import" class="p-mr-2 p-d-inline-block" />
<Button label="Export" icon="pi pi-upload" class="p-button-help" @click="exportCSV($event)" />
</template>
</Toolbar>
<DataTable ref="dt" :value="products" v-model:selection="selectedProducts" dataKey="id"
:paginator="true" :rows="10" :filters="filters"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[5,10,25]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} products">
<template #header>
<div class="table-header">
<h5 class="p-m-0">Manage Products</h5>
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Search..." />
</span>
</div>
</template>
<Column selectionMode="multiple" headerStyle="width: 3rem" :exportable="false"></Column>
<Column field="code" header="Code" :sortable="true"></Column>
<Column field="name" header="Name" :sortable="true"></Column>
<Column header="Image">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" :alt="slotProps.data.image" class="product-image" />
</template>
</Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
<Column field="category" header="Category" :sortable="true"></Column>
<Column field="rating" header="Reviews" :sortable="true">
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" :sortable="true">
<template #body="slotProps">
<span :class="'product-badge status-' + (slotProps.data.inventoryStatus ? slotProps.data.inventoryStatus.toLowerCase() : '')">{{slotProps.data.inventoryStatus}}</span>
</template>
</Column>
<Column :exportable="false">
<template #body="slotProps">
<Button icon="pi pi-pencil" class="p-button-rounded p-button-success p-mr-2" @click="editProduct(slotProps.data)" />
<Button icon="pi pi-trash" class="p-button-rounded p-button-warning" @click="confirmDeleteProduct(slotProps.data)" />
</template>
</Column>
</DataTable>
</div>
<Dialog v-model:visible="productDialog" :style="{width: '450px'}" header="Product Details" :modal="true" class="p-fluid">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" :alt="product.image" class="product-image" v-if="product.image" />
<div class="p-field">
<label for="name">Name</label>
<InputText id="name" v-model.trim="product.name" required="true" autofocus :class="{'p-invalid': submitted && !product.name}" />
<small class="p-error" v-if="submitted && !product.name">Name is required.</small>
</div>
<div class="p-field">
<label for="description">Description</label>
<Textarea id="description" v-model="product.description" required="true" rows="3" cols="20" />
</div>
<div class="p-field">
<label for="inventoryStatus" class="p-mb-3">Inventory Status</label>
<Dropdown id="inventoryStatus" v-model="product.inventoryStatus" :options="statuses" optionLabel="label" placeholder="Select a Status">
<template #value="slotProps">
<div v-if="slotProps.value && slotProps.value.value">
<span :class="'product-badge status-' +slotProps.value.value">{{slotProps.value.label}}</span>
</div>
<div v-else-if="slotProps.value && !slotProps.value.value">
<span :class="'product-badge status-' +slotProps.value.toLowerCase()">{{slotProps.value}}</span>
</div>
<span v-else>
{{slotProps.placeholder}}
</span>
</template>
</Dropdown>
</div>
<div class="p-field">
<label class="p-mb-3">Category</label>
<div class="p-formgrid p-grid">
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category1" name="category" value="Accessories" v-model="product.category" />
<label for="category1">Accessories</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category2" name="category" value="Clothing" v-model="product.category" />
<label for="category2">Clothing</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category3" name="category" value="Electronics" v-model="product.category" />
<label for="category3">Electronics</label>
</div>
<div class="p-field-radiobutton p-col-6">
<RadioButton id="category4" name="category" value="Fitness" v-model="product.category" />
<label for="category4">Fitness</label>
</div>
</div>
</div>
<div class="p-formgrid p-grid">
<div class="p-field p-col">
<label for="price">Price</label>
<InputNumber id="price" v-model="product.price" mode="currency" currency="USD" locale="en-US" />
</div>
<div class="p-field p-col">
<label for="quantity">Quantity</label>
<InputNumber id="quantity" v-model="product.quantity" integeronly />
</div>
</div>
<template #footer>
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog"/>
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="saveProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
<div class="confirmation-content">
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
<span v-if="product">Are you sure you want to delete <b>{{product.name}}</b>?</span>
</div>
<template #footer>
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductDialog = false"/>
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteProduct" />
</template>
</Dialog>
<Dialog v-model:visible="deleteProductsDialog" :style="{width: '450px'}" header="Confirm" :modal="true">
<div class="confirmation-content">
<i class="pi pi-exclamation-triangle p-mr-3" style="font-size: 2rem" />
<span v-if="product">Are you sure you want to delete the selected products?</span>
</div>
<template #footer>
<Button label="No" icon="pi pi-times" class="p-button-text" @click="deleteProductsDialog = false"/>
<Button label="Yes" icon="pi pi-check" class="p-button-text" @click="deleteSelectedProducts" />
</template>
</Dialog>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default {
data() {
return {
products: null,
productDialog: false,
deleteProductDialog: false,
deleteProductsDialog: false,
product: {},
selectedProducts: null,
filters: {},
submitted: false,
statuses: [
{label: 'INSTOCK', value: 'instock'},
{label: 'LOWSTOCK', value: 'lowstock'},
{label: 'OUTOFSTOCK', value: 'outofstock'}
]
} }
}, },
productService: null, productService: null,
@ -538,6 +719,128 @@ export default {
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000}); this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000});
} }
} }
}`,
style: `<style scoped>
.table-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.product-image {
width: 75px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23);
}
.p-dialog .product-image {
width: 150px;
margin: 0 auto 2rem auto;
display: block;
}
.confirmation-content {
display: flex;
align-items: center;
justify-content: center;
}
</style>`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProducts().then(data => this.products = data);
},
methods: {
formatCurrency(value) {
if(value)
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
return;
},
openNew() {
this.product = {};
this.submitted = false;
this.productDialog = true;
},
hideDialog() {
this.productDialog = false;
this.submitted = false;
},
saveProduct() {
this.submitted = true;
if (this.product.name.trim()) {
if (this.product.id) {
this.product.inventoryStatus = this.product.inventoryStatus.value ? this.product.inventoryStatus.value: this.product.inventoryStatus;
this.products[this.findIndexById(this.product.id)] = this.product;
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Updated', life: 3000});
}
else {
this.product.id = this.createId();
this.product.code = this.createId();
this.product.image = 'product-placeholder.svg';
this.product.inventoryStatus = this.product.inventoryStatus ? this.product.inventoryStatus.value : 'INSTOCK';
this.products.push(this.product);
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Created', life: 3000});
}
this.productDialog = false;
this.product = {};
}
},
editProduct(product) {
this.product = {...product};
this.productDialog = true;
},
confirmDeleteProduct(product) {
this.product = product;
this.deleteProductDialog = true;
},
deleteProduct() {
this.products = this.products.filter(val => val.id !== this.product.id);
this.deleteProductDialog = false;
this.product = {};
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Product Deleted', life: 3000});
},
findIndexById(id) {
let index = -1;
for (let i = 0; i < this.products.length; i++) {
if (this.products[i].id === id) {
index = i;
break;
}
}
return index;
},
createId() {
let id = '';
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for ( var i = 0; i < 5; i++ ) {
id += chars.charAt(Math.floor(Math.random() * chars.length));
}
return id;
},
exportCSV() {
this.$refs.dt.exportCSV();
},
confirmDeleteSelected() {
this.deleteProductsDialog = true;
},
deleteSelectedProducts() {
this.products = this.products.filter(val => !this.selectedProducts.includes(val));
this.deleteProductsDialog = false;
this.selectedProducts = null;
this.$toast.add({severity:'success', summary: 'Successful', detail: 'Products Deleted', life: 3000});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -2479,9 +2479,12 @@ export default {
</TabPanel> </TabPanel>
<TabPanel header="Source"> <TabPanel header="Source">
<a href="https://github.com/primefaces/primevue/tree/master/src/views/datatabledemo" class="btn-viewsource" target="_blank" rel="noopener noreferrer"> <div class="p-d-flex p-jc-between">
<span>View on GitHub</span> <a href="https://github.com/primefaces/primevue/tree/master/src/views/datatabledemo" class="btn-viewsource" target="_blank" rel="noopener noreferrer">
</a> <span>View on GitHub</span>
</a>
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-large" :components="['Column', 'InputText', 'MultiSelect', 'Calendar', 'Dropdown', 'ProgressBar', 'Button']" />
</div>
<pre v-code.script> <pre v-code.script>
<code> <code>
&#123; &#123;
@ -2773,3 +2776,279 @@ export default {
</TabView> </TabView>
</div> </div>
</template> </template>
<script>
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10"
dataKey="id" :rowHover="true" v-model:selection="selectedCustomers" :filters="filters" :loading="loading"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown" :rowsPerPageOptions="[10,25,50]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries">
<template #header>
<div class="table-header">
List of Customers
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Global Search" />
</span>
</div>
</template>
<template #empty>
No customers found.
</template>
<template #loading>
Loading customers data. Please wait.
</template>
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
<Column field="name" header="Name" :sortable="true">
<template #body="slotProps">
<span class="p-column-title">Name</span>
{{slotProps.data.name}}
</template>
<template #filter>
<InputText type="text" v-model="filters['name']" class="p-column-filter" placeholder="Search by name"/>
</template>
</Column>
<Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains">
<template #body="slotProps">
<span class="p-column-title">Country</span>
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
<template #filter>
<InputText type="text" v-model="filters['country.name']" class="p-column-filter" placeholder="Search by country"/>
</template>
</Column>
<Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in">
<template #body="slotProps">
<span class="p-column-title">Representative</span>
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #filter>
<MultiSelect v-model="filters['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter">
<template #option="slotProps">
<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" />
<span class="image-text">{{slotProps.option.name}}</span>
</div>
</template>
</MultiSelect>
</template>
</Column>
<Column field="date" header="Date" :sortable="true" filterMatchMode="custom" :filterFunction="filterDate">
<template #body="slotProps">
<span class="p-column-title">Date</span>
<span>{{slotProps.data.date}}</span>
</template>
<template #filter>
<Calendar v-model="filters['date']" dateFormat="yy-mm-dd" class="p-column-filter" placeholder="Registration Date"/>
</template>
</Column>
<Column field="status" header="Status" :sortable="true" filterMatchMode="equals">
<template #body="slotProps">
<span class="p-column-title">Status</span>
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
<template #filter>
<Dropdown v-model="filters['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true">
<template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template>
</Dropdown>
</template>
</Column>
<Column field="activity" header="Activity" :sortable="true" filterMatchMode="gte">
<template #body="slotProps">
<span class="p-column-title">Activity</span>
<ProgressBar :value="slotProps.data.activity" :showValue="false" />
</template>
<template #filter>
<InputText type="text" v-model="filters['activity']" class="p-column-filter" placeholder="Minimum"/>
</template>
</Column>
<Column headerStyle="width: 8rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<template #body>
<Button type="button" icon="pi pi-cog" class="p-button-secondary"></Button>
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default {
data() {
return {
customers: null,
selectedCustomers: null,
filters: {},
loading: true,
representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'},
{name: "Anna Fali", image: 'annafali.png'},
{name: "Asiya Javayant", image: 'asiyajavayant.png'},
{name: "Bernardo Dominic", image: 'bernardodominic.png'},
{name: "Elwin Sharvill", image: 'elwinsharvill.png'},
{name: "Ioni Bowcher", image: 'ionibowcher.png'},
{name: "Ivan Magalhaes",image: 'ivanmagalhaes.png'},
{name: "Onyama Limba", image: 'onyamalimba.png'},
{name: "Stephen Shaw", image: 'stephenshaw.png'},
{name: "XuXue Feng", image: 'xuxuefeng.png'}
],
statuses: [
'unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal'
]
}
},
created() {
this.customerService = new CustomerService();
},
mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data);
this.loading = false;
},
methods: {
filterDate(value, filter) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return true;
}
if (value === undefined || value === null) {
return false;
}
return value === this.formatDate(filter);
},
formatDate(date) {
let month = date.getMonth() + 1;
let day = date.getDate();
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
}
}
}`,
style: `<style lang="scss" scoped>
::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;
}
}
}
}
}
}
</style>`
}
}
}
},
components: {
LiveEditor
}
}
</script>

View File

@ -18,6 +18,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products"&gt; &lt;DataTable :value="products"&gt;
@ -62,7 +65,28 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
columns: null,
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products">
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
return { return {
@ -70,6 +94,25 @@ export default {
products: null products: null
} }
}, },
created() {
this.productService = new ProductService();
this.columns = [
{field: 'code', header: 'Code'},
{field: 'name', header: 'Name'},
{field: 'category', header: 'Category'},
{field: 'quantity', header: 'Quantity'}
];
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
}
}
`
}
}
}
},
productService: null, productService: null,
created() { created() {
this.productService = new ProductService(); this.productService = new ProductService();
@ -83,6 +126,9 @@ export default {
}, },
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
} }
} }
</script> </script>

View File

@ -95,6 +95,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column', 'InputText', 'Dropdown']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;h5&gt;Basic Cell Editing&lt;/h5&gt; &lt;h5&gt;Basic Cell Editing&lt;/h5&gt;
@ -297,6 +300,7 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default { export default {
data() { data() {
@ -307,7 +311,117 @@ export default {
products1: null, products1: null,
products2: null, products2: null,
products3: null, products3: null,
statuses: [{label: 'In Stock', value: 'INSTOCK'},{label: 'Low Stock', value: 'LOWSTOCK'},{label: 'Out of Stock', value: 'OUTOFSTOCK'}] statuses: [
{label: 'In Stock', value: 'INSTOCK'},
{label: 'Low Stock', value: 'LOWSTOCK'},
{label: 'Out of Stock', value: 'OUTOFSTOCK'}
],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation p-fluid">
<div class="card">
<h5>Basic Cell Editing</h5>
<p>Simple editors with v-model.</p>
<DataTable :value="products1" editMode="cell" class="editable-cells-table">
<Column field="code" header="Code">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="name" header="Name">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="inventoryStatus" header="Status">
<template #editor="slotProps">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" laceholder="Select a Status">
<template #option="slotProps">
<span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span>
</template>
</Dropdown>
</template>
<template #body="slotProps">
{{getStatusLabel(slotProps.data.inventoryStatus)}}
</template>
</Column>
<Column field="price" header="Price">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Advanced Cell Editing</h5>
<p>Custom implementation with validations, dynamic columns and reverting values with the escape key.</p>
<DataTable :value="products2" editMode="cell" @cell-edit-complete="onCellEditComplete" class="editable-cells-table" >
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field">
<template #editor="slotProps">
<InputText :modelValue="slotProps.data[slotProps.column.props.field]" @update:modelValue="onCellEdit($event, slotProps)" />
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Row Editing</h5>
<DataTable :value="products3" editMode="row" dataKey="id" v-model:editingRows="editingRows"
@row-edit-init="onRowEditInit" @row-edit-cancel="onRowEditCancel">
<Column field="code" header="Code">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" autofocus />
</template>
</Column>
<Column field="name" header="Name">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="inventoryStatus" header="Status">
<template #editor="slotProps">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" laceholder="Select a Status">
<template #option="slotProps">
<span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span>
</template>
</Dropdown>
</template>
<template #body="slotProps">
{{getStatusLabel(slotProps.data.inventoryStatus)}}
</template>
</Column>
<Column field="price" header="Price">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column :rowEditor="true" headerStyle="width:7rem" bodyStyle="text-align:center"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default {
data() {
return {
editingCellRows: {},
editingRows: [],
columns: null,
products1: null,
products2: null,
products3: null,
statuses: [
{label: 'In Stock', value: 'INSTOCK'},
{label: 'Low Stock', value: 'LOWSTOCK'},
{label: 'Out of Stock', value: 'OUTOFSTOCK'}
]
} }
}, },
originalRows: null, originalRows: null,
@ -393,6 +507,103 @@ export default {
this.productService.getProductsSmall().then(data => this.products2 = data); this.productService.getProductsSmall().then(data => this.products2 = data);
this.productService.getProductsSmall().then(data => this.products3 = data); this.productService.getProductsSmall().then(data => this.products3 = data);
} }
}`,
style: `<style lang="scss" scoped>
::v-deep(.editable-cells-table td.p-cell-editing) {
padding-top: 0;
padding-bottom: 0;
}
</style>`
}
}
}
},
originalRows: null,
productService: null,
created() {
this.productService = new ProductService();
this.columns = [
{field: 'code', header: 'Code'},
{field: 'name', header: 'Name'},
{field: 'quantity', header: 'Quantity'},
{field: 'price', header: 'Price'}
];
this.originalRows = {};
},
methods: {
onCellEditComplete(event) {
if (!this.editingCellRows[event.index]) {
return;
}
const editingCellValue = this.editingCellRows[event.index][event.field];
switch (event.field) {
case 'quantity':
case 'price':
if (this.isPositiveInteger(editingCellValue))
this.products2[event.index] = {...this.editingCellRows[event.index]};
else
event.preventDefault();
break;
default:
if (editingCellValue.trim().length > 0)
this.products2[event.index] = {...this.editingCellRows[event.index]};
else
event.preventDefault();
break;
}
},
onCellEdit(newValue, props) {
if (!this.editingCellRows[props.index]) {
this.editingCellRows[props.index] = {...props.data};
}
this.editingCellRows[props.index][props.column.props.field] = newValue;
},
isPositiveInteger(val) {
let str = String(val);
str = str.trim();
if (!str) {
return false;
}
str = str.replace(/^0+/, "") || "0";
var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0;
},
onRowEditInit(event) {
this.originalRows[event.index] = {...this.products3[event.index]};
},
onRowEditCancel(event) {
this.products3[event.index] = this.originalRows[event.index];
},
getStatusLabel(status) {
switch(status) {
case 'INSTOCK':
return 'In Stock';
case 'LOWSTOCK':
return 'Low Stock';
case 'OUTOFSTOCK':
return 'Out of Stock';
default:
return 'NA';
}
}
},
mounted() {
this.productService.getProductsSmall().then(data => this.products1 = data);
this.productService.getProductsSmall().then(data => this.products2 = data);
this.productService.getProductsSmall().then(data => this.products3 = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -26,6 +26,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column', 'Button']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" ref="dt"&gt; &lt;DataTable :value="products" ref="dt"&gt;
@ -75,6 +78,36 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" ref="dt">
<template #header>
<div style="text-align: left">
<Button icon="pi pi-external-link" label="Export" @click="exportCSV($event)" />
</div>
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -94,5 +127,25 @@ export default {
this.$refs.dt.exportCSV(); this.$refs.dt.exportCSV();
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
exportCSV() {
this.$refs.dt.exportCSV();
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -100,6 +100,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-large" :components="['Column', 'InputText', 'MultiSelect', 'Calendar', 'Dropdown', 'ProgressBar', 'Button']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <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"
@ -262,7 +265,126 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
customers: null,
filters: {},
loading: true,
representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'},
{name: "Anna Fali", image: 'annafali.png'},
{name: "Asiya Javayant", image: 'asiyajavayant.png'},
{name: "Bernardo Dominic", image: 'bernardodominic.png'},
{name: "Elwin Sharvill", image: 'elwinsharvill.png'},
{name: "Ioni Bowcher", image: 'ionibowcher.png'},
{name: "Ivan Magalhaes",image: 'ivanmagalhaes.png'},
{name: "Onyama Limba", image: 'onyamalimba.png'},
{name: "Stephen Shaw", image: 'stephenshaw.png'},
{name: "XuXue Feng", image: 'xuxuefeng.png'}
],
statuses: [
'unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal'
],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="customers" :paginator="true" class="p-datatable-customers" :rows="10"
dataKey="id" :filters="filters" :loading="loading">
<template #header>
<div class="table-header">
List of Customers
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters['global']" placeholder="Global Search" />
</span>
</div>
</template>
<template #empty>
No customers found.
</template>
<template #loading>
Loading customers data. Please wait.
</template>
<Column field="name" header="Name">
<template #body="slotProps">
<span class="p-column-title">Name</span>
{{slotProps.data.name}}
</template>
<template #filter>
<InputText type="text" v-model="filters['name']" class="p-column-filter" placeholder="Search by name"/>
</template>
</Column>
<Column header="Country" filterField="country.name" filterMatchMode="contains">
<template #body="slotProps">
<span class="p-column-title">Country</span>
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" :class="'flag flag-' + slotProps.data.country.code" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
<template #filter>
<InputText type="text" v-model="filters['country.name']" class="p-column-filter" placeholder="Search by country"/>
</template>
</Column>
<Column header="Representative" filterField="representative.name" filterMatchMode="in">
<template #body="slotProps">
<span class="p-column-title">Representative</span>
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #filter>
<MultiSelect v-model="filters['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter">
<template #option="slotProps">
<div class="p-multiselect-representative-option">
<img :alt="slotProps.option.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.option.name}}</span>
</div>
</template>
</MultiSelect>
</template>
</Column>
<Column field="date" header="Date" filterMatchMode="custom" :filterFunction="filterDate">
<template #body="slotProps">
<span class="p-column-title">Date</span>
<span>{{slotProps.data.date}}</span>
</template>
<template #filter>
<Calendar v-model="filters['date']" dateFormat="yy-mm-dd" class="p-column-filter" placeholder="Registration Date"/>
</template>
</Column>
<Column field="status" header="Status" filterMatchMode="equals">
<template #body="slotProps">
<span class="p-column-title">Status</span>
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
<template #filter>
<Dropdown v-model="filters['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true">
<template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template>
</Dropdown>
</template>
</Column>
<Column field="activity" header="Activity" filterMatchMode="gte">
<template #body="slotProps">
<span class="p-column-title">Activity</span>
<ProgressBar :value="slotProps.data.activity" :showValue="false" />
</template>
<template #filter>
<InputText type="text" v-model="filters['activity']" class="p-column-filter" placeholder="Minimum"/>
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
return { return {
@ -321,6 +443,144 @@ export default {
} }
} }
} }
`,
style: `<style lang="scss" scoped>
::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;
}
}
}
}
}
}
</style>`
}
}
}
},
created() {
this.customerService = new CustomerService();
},
mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data);
this.loading = false;
},
methods: {
filterDate(value, filter) {
if (filter === undefined || filter === null || (typeof filter === 'string' && filter.trim() === '')) {
return true;
}
if (value === undefined || value === null) {
return false;
}
return value === this.formatDate(filter);
},
formatDate(date) {
let month = date.getMonth() + 1;
let day = date.getDate();
if (month < 10) {
month = '0' + month;
}
if (day < 10) {
day = '0' + day;
}
return date.getFullYear() + '-' + month + '-' + day;
}
},
components: {
LiveEditor
}
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -27,6 +27,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" class="p-datatable-gridlines"&gt; &lt;DataTable :value="products" class="p-datatable-gridlines"&gt;
@ -72,7 +75,37 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" class="p-datatable-gridlines">
<template #header>
Header
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
<template #footer>
Footer
</template>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
return { return {
@ -86,5 +119,20 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -41,6 +41,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" :components="['Column', 'InputText']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" :filters="filters" ref="dt" &lt;DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" :filters="filters" ref="dt"
@ -149,6 +152,63 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
loading: false,
totalRecords: 0,
customers: null,
filters: {
'name': {value: '', matchMode: 'contains'},
'country.name': {value: '', matchMode: 'contains'},
'company': {value: '', matchMode: 'contains'},
'representative.name': {value: '', matchMode: 'contains'},
},
lazyParams: {},
columns: [
{field: 'name', header: 'Name'},
{field: 'country.name', header: 'Country'},
{field: 'company', header: 'Company'},
{field: 'representative.name', header: 'Representative'}
],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="customers" :lazy="true" :paginator="true" :rows="10" :filters="filters" ref="dt"
:totalRecords="totalRecords" :loading="loading" @page="onPage($event)" @sort="onSort($event)">
<Column field="name" header="Name" filterMatchMode="startsWith" ref="name" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters['name']['value']" @keydown.enter="onFilter($event)" class="p-column-filter" placeholder="Search by name"/>
</template>
</Column>
<Column field="country.name" header="Country" filterField="country.name" filterMatchMode="contains" ref="country.name" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters['country.name']['value']" @keydown.enter="onFilter($event)" class="p-column-filter" placeholder="Search by country"/>
</template>
</Column>
<Column field="company" header="Company" filterMatchMode="contains" ref="company" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters['company']['value']" @keydown.enter="onFilter($event)" class="p-column-filter" placeholder="Search by company"/>
</template>
</Column>
<Column field="representative.name" header="Representative" filterField="representative.name" ref="representative.name" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters['representative.name']['value']" @keydown.enter="onFilter($event)" class="p-column-filter" placeholder="Search by representative"/>
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
@ -212,5 +272,54 @@ export default {
this.loadLazyData(); this.loadLazyData();
} }
} }
}`
}
}
}
},
customerService: null,
created() {
this.customerService = new CustomerService();
},
mounted() {
this.loading = true;
this.lazyParams = {
first: 0,
rows: this.$refs.dt.rows,
sortField: null,
sortOrder: null,
filters: this.filters
};
this.loadLazyData();
},
methods: {
loadLazyData() {
this.loading = true;
this.customerService.getCustomers({lazyEvent: JSON.stringify( this.lazyParams )}).then(data => {
this.customers = data.customers;
this.totalRecords = data.totalRecords;
this.loading = false;
});
},
onPage(event) {
this.lazyParams = event;
this.loadLazyData();
},
onSort(event) {
this.lazyParams = event;
this.loadLazyData();
},
onFilter() {
this.loading = true;
this.lazyParams.filters = this.filters;
this.loadLazyData();
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -30,6 +30,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-large" :components="['Column', 'Button']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="customers" :paginator="true" :rows="10" &lt;DataTable :value="customers" :paginator="true" :rows="10"
@ -78,6 +81,40 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
customers: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="customers" :paginator="true" :rows="10"
paginatorTemplate="CurrentPageReport FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink RowsPerPageDropdown"
:rowsPerPageOptions="[10,20,50]"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords}">
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="company" header="Company"></Column>
<Column field="representative.name" header="Representative"></Column>
<template #paginatorLeft>
<Button type="button" icon="pi pi-refresh" class="p-button-text" />
</template>
<template #paginatorRight>
<Button type="button" icon="pi pi-cloud" class="p-button-text" />
</template>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
@ -92,5 +129,20 @@ export default {
mounted() { mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data); this.customerService.getCustomersLarge().then(data => this.customers = data);
} }
}`
}
}
}
},
customerService: null,
created() {
this.customerService = new CustomerService();
},
mounted() {
this.customerService.getCustomersLarge().then(data => this.customers = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -19,6 +19,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" :reorderableColumns="true" @column-reorder="onColReorder" @row-reorder="onRowReorder"&gt; &lt;DataTable :value="products" :reorderableColumns="true" @column-reorder="onColReorder" @row-reorder="onRowReorder"&gt;
@ -73,6 +76,31 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
columns: null,
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<Toast />
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" :reorderableColumns="true" @column-reorder="onColReorder" @row-reorder="onRowReorder">
<Column :rowReorder="true" headerStyle="width: 3rem" :reorderableColumn="false" />
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -104,5 +132,36 @@ export default {
this.$toast.add({severity:'success', summary: 'Rows Reordered', life: 3000}); this.$toast.add({severity:'success', summary: 'Rows Reordered', life: 3000});
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
this.columns = [
{field: 'code', header: 'Code'},
{field: 'name', header: 'Name'},
{field: 'category', header: 'Category'},
{field: 'quantity', header: 'Quantity'}
];
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
onColReorder() {
this.$toast.add({severity:'success', summary: 'Column Reordered', life: 3000});
},
onRowReorder(event) {
this.products = event.value;
this.$toast.add({severity:'success', summary: 'Rows Reordered', life: 3000});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -44,6 +44,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" class="p-datatable-responsive-demo" :paginator="true" :rows="10"&gt; &lt;DataTable :value="products" class="p-datatable-responsive-demo" :paginator="true" :rows="10"&gt;
@ -146,6 +149,54 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" class="p-datatable-responsive-demo" :paginator="true" :rows="10">
<template #header>
Responsive
</template>
<Column field="code" header="Code">
<template #body="slotProps">
<span class="p-column-title">Code</span>
{{slotProps.data.code}}
</template>
</Column>
<Column field="name" header="Name">
<template #body="slotProps">
<span class="p-column-title">Name</span>
{{slotProps.data.name}}
</template>
</Column>
<Column field="category" header="Category">
<template #body="slotProps">
<span class="p-column-title">Category</span>
{{slotProps.data.category}}
</template>
</Column>
<Column field="quantity" header="Quantity">
<template #body="slotProps">
<span class="p-column-title">Quantity</span>
{{slotProps.data.quantity}}
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -160,6 +211,58 @@ export default {
mounted() { mounted() {
this.productService.getProducts().then(data => this.products = data); this.productService.getProducts().then(data => this.products = data);
} }
}`,
style: `<style lang="scss" scoped>
.p-datatable-responsive-demo .p-datatable-tbody > tr > td .p-column-title {
display: none;
}
@media screen and (max-width: 40em) {
::v-deep(.p-datatable) {
&.p-datatable-responsive-demo {
.p-datatable-thead > tr > th,
.p-datatable-tfoot > tr > td {
display: none !important;
}
.p-datatable-tbody > tr > td {
text-align: left;
display: block;
width: 100%;
float: left;
clear: left;
border: 0 none;
.p-column-title {
padding: .4rem;
min-width: 30%;
display: inline-block;
margin: -.4em 1em -.4em -.4rem;
font-weight: bold;
}
&:last-child {
border-bottom: 1px solid var(--surface-d);
}
}
}
}
}
</style>`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProducts().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -72,6 +72,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-orders-small" :components="['Column', 'Button', 'Rating']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" v-model:expandedRows="expandedRows" dataKey="id" &lt;DataTable :value="products" v-model:expandedRows="expandedRows" dataKey="id"
@ -182,6 +185,84 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
expandedRows: [],
sources: {
'template': {
content:`<template>
<div class="layout-content">
<Toast />
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" v-model:expandedRows="expandedRows" dataKey="id"
@row-expand="onRowExpand" @row-collapse="onRowCollapse">
<template #header>
<div class="table-header-container">
<Button icon="pi pi-plus" label="Expand All" @click="expandAll" class="p-mr-2" />
<Button icon="pi pi-minus" label="Collapse All" @click="collapseAll" />
</div>
</template>
<Column :expander="true" headerStyle="width: 3rem" />
<Column field="name" header="Name" sortable></Column>
<Column header="Image">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" :alt="slotProps.data.image" class="product-image" />
</template>
</Column>
<Column field="price" header="Price" sortable>
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
<Column field="category" header="Category" sortable></Column>
<Column field="rating" header="Reviews" sortable>
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" sortable>
<template #body="slotProps">
<span :class="'product-badge status-' + slotProps.data.inventoryStatus.toLowerCase()">{{slotProps.data.inventoryStatus}}</span>
</template>
</Column>
<template #expansion="slotProps">
<div class="orders-subtable">
<h5>Orders for {{slotProps.data.name}}</h5>
<DataTable :value="slotProps.data.orders">
<Column field="id" header="Id" sortable></Column>
<Column field="customer" header="Customer" sortable></Column>
<Column field="date" header="Date" sortable></Column>
<Column field="amount" header="Amount" sortable>
<template #body="slotProps" sortable>
{{formatCurrency(slotProps.data.amount)}}
</template>
</Column>
<Column field="status" header="Status" sortable>
<template #body="slotProps">
<span :class="'order-badge order-' + slotProps.data.status.toLowerCase()">{{slotProps.data.status}}</span>
</template>
</Column>
<Column headerStyle="width:4rem">
<template #body>
<Button icon="pi pi-search" />
</template>
</Column>
</DataTable>
</div>
</template>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -216,6 +297,50 @@ export default {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'}); return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
} }
} }
}`,
style: `<style lang="scss" scoped>
.product-image {
width: 100px;
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23)
}
.orders-subtable {
padding: 1rem;
}
</style>`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsWithOrdersSmall().then(data => this.products = data);
},
methods: {
onRowExpand(event) {
this.$toast.add({severity: 'info', summary: 'Product Expanded', detail: event.data.name, life: 3000});
},
onRowCollapse(event) {
this.$toast.add({severity: 'success', summary: 'Product Collapsed', detail: event.data.name, life: 3000});
},
expandAll() {
this.expandedRows = this.products.filter(p => p.id);
this.$toast.add({severity: 'success', summary: 'All Rows Expanded', life: 3000});
},
collapseAll() {
this.expandedRows = null;
this.$toast.add({severity: 'success', summary: 'All Rows Collapsed', life: 3000});
},
formatCurrency(value) {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -108,6 +108,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-medium" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -258,6 +261,120 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
customers: null,
expandedRowGroups: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<Toast />
<div class="content-section implementation">
<div class="card">
<h5>Subheader Grouping</h5>
<p>Group customers by their representative.</p>
<DataTable :value="customers" rowGroupMode="subheader" groupRowsBy="representative.name"
sortMode="single" sortField="representative.name" :sortOrder="1">
<Column field="representative.name" header="Representative"></Column>
<Column field="name" header="Name"></Column>
<Column field="country" header="Country">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
</Column>
<Column field="company" header="Company"></Column>
<Column field="status" header="Status">
<template #body="slotProps">
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
</Column>
<Column field="date" header="Date"></Column>
<template #groupheader="slotProps">
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #groupfooter="slotProps">
<td colspan="4" style="text-align: right">Total Customers</td>
<td>{{calculateCustomerTotal(slotProps.data.representative.name)}}</td>
</template>
</DataTable>
</div>
<div class="card">
<h5>Expandable Row Groups</h5>
<p>Group customers by their representative.</p>
<DataTable :value="customers" rowGroupMode="subheader" groupRowsBy="representative.name"
sortMode="single" sortField="representative.name" :sortOrder="1"
:expandableRowGroups="true" v-model:expandedRowGroups="expandedRowGroups"
@rowgroup-expand="onRowGroupExpand" @rowgroup-collapse="onRowGroupCollapse">
<Column field="representative.name" header="Representative"></Column>
<Column field="name" header="Name"></Column>
<Column field="country" header="Country">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
</Column>
<Column field="company" header="Company"></Column>
<Column field="status" header="Status">
<template #body="slotProps">
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
</Column>
<Column field="date" header="Date"></Column>
<template #groupheader="slotProps">
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #groupfooter="slotProps">
<td colspan="4" style="text-align: right">Total Customers</td>
<td>{{calculateCustomerTotal(slotProps.data.representative.name)}}</td>
</template>
</DataTable>
</div>
<div class="card">
<h5>RowSpan Grouping</h5>
<DataTable :value="customers" rowGroupMode="rowspan" groupRowsBy="representative.name"
sortMode="single" sortField="representative.name" :sortOrder="1">
<Column header="#" headerStyle="width:3em">
<template #body="slotProps">
{{slotProps.index}}
</template>
</Column>
<Column field="representative.name" header="Representative">
<template #body="slotProps">
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
</Column>
<Column field="name" header="Name"></Column>
<Column field="country" header="Country">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="20" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
</Column>
<Column field="company" header="Company"></Column>
<Column field="status" header="Status">
<template #body="slotProps">
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
</Column>
<Column field="date" header="Date"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
@ -294,6 +411,65 @@ export default {
return total; return total;
} }
} }
}`,
style: `
<style lang="scss" scoped>
.p-rowgroup-footer td {
font-weight: 700;
}
::v-deep(.p-rowgroup-header) {
span {
font-weight: 700;
}
.p-row-toggler {
vertical-align: middle;
margin-right: .25rem;
}
}
.image-text {
vertical-align: middle;
}
img {
vertical-align: middle;
}
</style>`
}
}
}
},
customerService: null,
created() {
this.customerService = new CustomerService();
},
mounted() {
this.customerService.getCustomersMedium().then(data => this.customers = data);
},
methods: {
onRowGroupExpand(event) {
this.$toast.add({severity: 'info', summary: 'Row Group Expanded', detail: 'Value: ' + event.data, life: 3000});
},
onRowGroupCollapse(event) {
this.$toast.add({severity: 'success', summary: 'Row Group Collapsed', detail: 'Value: ' + event.data, life: 3000});
},
calculateCustomerTotal(name) {
let total = 0;
if (this.customers) {
for (let customer of this.customers) {
if (customer.representative.name === name) {
total++;
}
}
}
return total;
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -111,6 +111,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-large" :components="['Column', 'Dialog', 'Button']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -319,6 +322,126 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
customers: null,
virtualCustomers: null,
lazyTotalRecords: 0,
frozenValue: null,
loading: false,
dialogVisible: false,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<h5>Vertical</h5>
<DataTable :value="customers" :scrollable="true" scrollHeight="200px" :loading="loading">
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="status" header="Status"></Column>
</DataTable>
</div>
<div class="card">
<h5>Flexible Scroll</h5>
<p>Flex scroll feature makes the scrollable viewport section dynamic so that it can grow or shrink relative to the parent size of the table.
Click the button below to display a maximizable Dialog where data viewport adjusts itself according to the size changes.</p>
<Button label="Show" icon="pi pi-external-link" @click="openDialog" />
</div>
<Dialog header="Flex Scroll" v-model:visible="dialogVisible" :style="{width: '75vw'}" :maximizable="true" :modal="true" :contentStyle="{height: '300px'}">
<DataTable :value="customers" :scrollable="true" scrollHeight="flex">
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="status" header="Company"></Column>
</DataTable>
<template #footer>
<Button label="Ok" icon="pi pi-check" @click="closeDialog" />
</template>
</Dialog>
<div class="card">
<h5>Virtual Scroll</h5>
<DataTable :value="virtualCustomers" :scrollable="true" scrollHeight="200px" :lazy="true" :rows="20" :loading="loading"
:virtualScroll="true" :virtualRowHeight="45" @virtual-scroll="onVirtualScroll" :totalRecords="lazyTotalRecords">
<Column field="name" header="Name">
<template #loading>
<span class="loading-text"></span>
</template>
</Column>
<Column field="country.name" header="Country">
<template #loading>
<span class="loading-text"></span>
</template>
</Column>
<Column field="representative.name" header="Representative">
<template #loading>
<span class="loading-text"></span>
</template>
</Column>
<Column field="status" header="Status">
<template #loading>
<span class="loading-text"></span>
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Horizontal and Vertical</h5>
<DataTable :value="customers" :scrollable="true" scrollHeight="200px" style="width: 600px" :loading="loading">
<Column field="id" header="Id" headerStyle="width: 250px" columnKey="id"></Column>
<Column field="name" header="Name" headerStyle="width: 250px" columnKey="name"></Column>
<Column field="country.name" header="Country" headerStyle="width: 250px" columnKey="country"></Column>
<Column field="date" header="Date" headerStyle="width: 250px" columnKey="date"></Column>
<Column field="company" header="Company" headerStyle="width: 250px" columnKey="company"></Column>
<Column field="status" header="Status" headerStyle="width: 250px" columnKey="status"></Column>
<Column field="activity" header="Activity" headerStyle="width: 250px" columnKey="activity"></Column>
<Column field="representative.name" header="Representative" headerStyle="width: 250px" columnKey="representative"></Column>
</DataTable>
</div>
<div class="card">
<h5>Frozen Rows</h5>
<DataTable :value="customers" :frozenValue="frozenValue" :scrollable="true" scrollHeight="200px" :loading="loading">
<Column field="name" header="Name"></Column>
<Column field="country.name" header="Country"></Column>
<Column field="representative.name" header="Representative"></Column>
<Column field="status" header="Status"></Column>
</DataTable>
</div>
<div class="card">
<h5>Frozen Columns</h5>
<DataTable :value="customers" :scrollable="true" scrollHeight="200px" frozenWidth="300px" :loading="loading">
<Column field="name" header="Name" headerStyle="width: 300px" columnKey="name" :frozen="true">
<template #body="slotProps">
<span style="font-weight: 700">{{slotProps.data.name}}</span>
</template>
</Column>
<Column field="id" header="Id" headerStyle="width: 300px" columnKey="id"></Column>
<Column field="country.name" header="Country" headerStyle="width: 300px" columnKey="country"></Column>
<Column field="date" header="Date" headerStyle="width: 300px" columnKey="date"></Column>
<Column field="company" header="Country" headerStyle="width: 300px" columnKey="company"></Column>
<Column field="status" header="Status" headerStyle="width: 300px" columnKey="status"></Column>
<Column field="activity" header="Activity" headerStyle="width: 300px" columnKey="activity"></Column>
<Column field="representative.name" header="Representative" headerStyle="width: 300px" columnKey="representative"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
@ -410,6 +533,103 @@ export default {
this.dialogVisible = false; this.dialogVisible = false;
} }
} }
}`,
style: `<style lang="scss" scoped>
.loading-text {
display: block;
background-color: #f1f1f1;
min-height: 19px;
animation: pulse 1s infinite ease-in-out;
text-indent: -99999px;
overflow: hidden;
}
</style>`
}
}
}
},
customerService: null,
inmemoryData: null,
created() {
this.customerService = new CustomerService();
},
mounted() {
this.loading = true;
this.customerService.getCustomersLarge().then(data => {
this.customers = data;
this.loading = false;
});
this.customerService.getCustomersXLarge().then(data => this.inmemoryData = data);
this.frozenValue = [
{
id: 1255,
name: "James McAdams",
country: {
name: "United States",
code: "us"
},
company: "McAdams Consulting Ltd",
date: "2014-02-13",
status: "qualified",
activity: 23,
representative: {
name: "Ioni Bowcher",
image: "ionibowcher.png"
}
},
{
id: 5135,
name: "Geraldine Bisset",
country: {
name: "France",
code: "fr"
},
company: "Bisset Group",
status: "proposal",
date: "2019-05-05",
activity: 0,
representative: {
name: "Amy Elsner",
image: "amyelsner.png"
}
}
];
setTimeout(() => {
this.virtualCustomers = this.loadChunk(0, 40);
this.lazyTotalRecords = 500;
}, 250);
},
methods: {
loadChunk(index, length) {
let chunk = [];
for (let i = 0; i < length; i++) {
chunk[i] = {...this.inmemoryData[i]};
}
return chunk;
},
onVirtualScroll(event) {
setTimeout(() => {
//last chunk
if (event.first === 480)
this.virtualCustomers = this.loadChunk(event.first, 20)
else
this.virtualCustomers = this.loadChunk(event.first, event.rows)
}, 250);
},
openDialog() {
this.dialogVisible = true;
},
closeDialog() {
this.dialogVisible = false;
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -84,6 +84,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -202,6 +205,101 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
selectedProduct1: null,
selectedProduct2: null,
selectedProduct3: null,
selectedProducts1: null,
selectedProducts2: null,
selectedProducts3: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<Toast />
<div class="card">
<h5>Single</h5>
<p>In single mode, a row is selected on click event of a row. If the row is already selected then the row gets unselected.</p>
<DataTable :value="products" v-model:selection="selectedProduct1" selectionMode="single" dataKey="id">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<h5>Multiple</h5>
<p>In multiple mode, selection binding should be an array. For touch enabled devices, selection is managed by tapping and for other devices metakey or shiftkey are required.
Setting metaKeySelection property as false enables multiple selection without meta key.</p>
<DataTable :value="products" v-model:selection="selectedProducts1" selectionMode="multiple" dataKey="id">
<template #header>
Multiple Selection with MetaKey
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
<DataTable :value="products" v-model:selection="selectedProducts2" selectionMode="multiple" dataKey="id" :metaKeySelection="false" style="margin-top: 2em">
<template #header>
Multiple Selection without MetaKey
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<h5>Events</h5>
<p>row-select and row-unselects are available as selection events.</p>
<DataTable :value="products" v-model:selection="selectedProduct2" selectionMode="single" dataKey="id"
@row-select="onRowSelect($event)" @row-unselect="onRowUnselect($event)">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<h5>RadioButton</h5>
<p>Single selection can also be handled using radio buttons by enabling the selectionMode property of column as "single".</p>
<DataTable :value="products" v-model:selection="selectedProduct3" dataKey="id">
<Column selectionMode="single" headerStyle="width: 3em"></Column>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<h5>Checkbox</h5>
<DataTable :value="products" v-model:selection="selectedProducts3" dataKey="id">
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -215,7 +313,7 @@ export default {
selectedProducts3: null selectedProducts3: null
} }
}, },
productService: null, productService: null,
created() { created() {
this.productService = new ProductService(); this.productService = new ProductService();
}, },
@ -230,5 +328,29 @@ export default {
this.$toast.add({severity: 'warn', summary: 'Product Unselected', detail: 'Name: ' + event.data.name, life: 3000}); this.$toast.add({severity: 'warn', summary: 'Product Unselected', detail: 'Name: ' + event.data.name, life: 3000});
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
onRowSelect(event) {
console.log(event)
this.$toast.add({severity: 'info', summary: 'Product Selected', detail: 'Name: ' + event.data.name, life: 3000});
},
onRowUnselect(event) {
this.$toast.add({severity: 'warn', summary: 'Product Unselected', detail: 'Name: ' + event.data.name, life: 3000});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -48,6 +48,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" class="p-datatable-sm"&gt; &lt;DataTable :value="products" class="p-datatable-sm"&gt;
@ -110,7 +113,58 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" class="p-datatable-sm">
<template #header>
Small Table
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<DataTable :value="products">
<template #header>
Normal Table
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
<div class="card">
<DataTable :value="products" class="p-datatable-lg">
<template #header>
Large Table
</template>
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
return { return {
@ -124,5 +178,20 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -73,6 +73,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -171,6 +174,83 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<h5>Single Column</h5>
<DataTable :value="products">
<Column field="code" header="Code" :sortable="true"></Column>
<Column field="name" header="Name" :sortable="true"></Column>
<Column field="category" header="Category" :sortable="true"></Column>
<Column field="quantity" header="Quantity" :sortable="true"></Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Multiple Columns</h5>
<p>Use metakey to add a column to the sort selection.</p>
<DataTable :value="products" sortMode="multiple">
<Column field="code" header="Code" :sortable="true"></Column>
<Column field="name" header="Name" :sortable="true"></Column>
<Column field="category" header="Category" :sortable="true"></Column>
<Column field="quantity" header="Quantity" :sortable="true"></Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Presort</h5>
<DataTable :value="products" sortField="category" :sortOrder="-1">
<Column field="code" header="Code" :sortable="true"></Column>
<Column field="name" header="Name" :sortable="true"></Column>
<Column field="category" header="Category" :sortable="true"></Column>
<Column field="quantity" header="Quantity" :sortable="true"></Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
</DataTable>
</div>
<div class="card">
<h5>Removable Sort</h5>
<DataTable :value="products" removableSort>
<Column field="code" header="Code" :sortable="true"></Column>
<Column field="name" header="Name" :sortable="true"></Column>
<Column field="category" header="Category" :sortable="true"></Column>
<Column field="quantity" header="Quantity" :sortable="true"></Column>
<Column field="price" header="Price" :sortable="true">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -190,5 +270,25 @@ export default {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'}); return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
formatCurrency(value) {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -130,6 +130,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="CustomerService" data="customers-medium" :components="['Column', 'InputText', 'MultiSelect', 'Dropdown']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;div class="card"&gt; &lt;div class="card"&gt;
@ -300,6 +303,159 @@ export default {
<script> <script>
import CustomerService from '../../service/CustomerService'; import CustomerService from '../../service/CustomerService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
customers: null,
selectedCustomer1: null,
selectedCustomer2: null,
filters1: {},
filters2: {},
loading: true,
representatives: [
{name: "Amy Elsner", image: 'amyelsner.png'},
{name: "Anna Fali", image: 'annafali.png'},
{name: "Asiya Javayant", image: 'asiyajavayant.png'},
{name: "Bernardo Dominic", image: 'bernardodominic.png'},
{name: "Elwin Sharvill", image: 'elwinsharvill.png'},
{name: "Ioni Bowcher", image: 'ionibowcher.png'},
{name: "Ivan Magalhaes",image: 'ivanmagalhaes.png'},
{name: "Onyama Limba", image: 'onyamalimba.png'},
{name: "Stephen Shaw", image: 'stephenshaw.png'},
{name: "XuXue Feng", image: 'xuxuefeng.png'}
],
statuses: [
'unqualified', 'qualified', 'new', 'negotiation', 'renewal', 'proposal'
],
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<h5>Session Storage</h5>
<DataTable :value="customers" :paginator="true" :rows="10" v-model:filters="filters1"
v-model:selection="selectedCustomer1" selectionMode="single" dataKey="id"
stateStorage="session" stateKey="dt-state-demo-session">
<template #header>
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters1['global']" placeholder="Global Search" />
</span>
</template>
<Column field="name" header="Name" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters1['name']" class="p-column-filter" placeholder="Search by name"/>
</template>
</Column>
<Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
<template #filter>
<InputText type="text" v-model="filters1['country.name']" class="p-column-filter" placeholder="Search by country"/>
</template>
</Column>
<Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in">
<template #body="slotProps">
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #filter>
<MultiSelect v-model="filters1['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter">
<template #option="slotProps">
<div class="p-multiselect-representative-option">
<img :alt="slotProps.option.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.option.name}}</span>
</div>
</template>
</MultiSelect>
</template>
</Column>
<Column field="status" header="Status" :sortable="true" filterMatchMode="equals">
<template #body="slotProps">
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
<template #filter>
<Dropdown v-model="filters1['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true">
<template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template>
</Dropdown>
</template>
</Column>
<template #empty>
No customers found.
</template>
</DataTable>
</div>
<div class="card">
<h5>Local Storage</h5>
<DataTable :value="customers" :paginator="true" :rows="10" v-model:filters="filters2"
v-model:selection="selectedCustomer2" selectionMode="single" dataKey="id"
stateStorage="session" stateKey="dt-state-demo-local">
<template #header>
<span class="p-input-icon-left">
<i class="pi pi-search" />
<InputText v-model="filters2['global']" placeholder="Global Search" />
</span>
</template>
<Column field="name" header="Name" :sortable="true">
<template #filter>
<InputText type="text" v-model="filters2['name']" class="p-column-filter" placeholder="Search by name"/>
</template>
</Column>
<Column header="Country" :sortable="true" sortField="country.name" filterField="country.name" filterMatchMode="contains">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="30" />
<span class="image-text">{{slotProps.data.country.name}}</span>
</template>
<template #filter>
<InputText type="text" v-model="filters2['country.name']" class="p-column-filter" placeholder="Search by country"/>
</template>
</Column>
<Column header="Representative" :sortable="true" sortField="representative.name" filterField="representative.name" filterMatchMode="in">
<template #body="slotProps">
<img :alt="slotProps.data.representative.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.data.representative.name}}</span>
</template>
<template #filter>
<MultiSelect v-model="filters2['representative.name']" :options="representatives" optionLabel="name" optionValue="name" placeholder="All" class="p-column-filter">
<template #option="slotProps">
<div class="p-multiselect-representative-option">
<img :alt="slotProps.option.name" src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" width="32" style="vertical-align: middle" />
<span class="image-text">{{slotProps.option.name}}</span>
</div>
</template>
</MultiSelect>
</template>
</Column>
<Column field="status" header="Status" :sortable="true" filterMatchMode="equals">
<template #body="slotProps">
<span :class="'customer-badge status-' + slotProps.data.status">{{slotProps.data.status}}</span>
</template>
<template #filter>
<Dropdown v-model="filters2['status']" :options="statuses" placeholder="Select a Status" class="p-column-filter" :showClear="true">
<template #option="slotProps">
<span :class="'customer-badge status-' + slotProps.option">{{slotProps.option}}</span>
</template>
</Dropdown>
</template>
</Column>
<template #empty>
No customers found.
</template>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import CustomerService from '../service/CustomerService';
export default { export default {
data() { data() {
@ -327,11 +483,27 @@ export default {
] ]
} }
}, },
customerService: null,
created() { created() {
this.customerService = new CustomerService(); this.customerService = new CustomerService();
}, },
mounted() { mounted() {
this.customerService.getCustomersMedium().then(data => this.customers = data); this.customerService.getCustomersMedium().then(data => this.customers = data);
} }
}`
}
}
}
},
customerService: null,
created() {
this.customerService = new CustomerService();
},
mounted() {
this.customerService.getCustomersMedium().then(data => this.customers = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -21,6 +21,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" class="p-datatable-striped"&gt; &lt;DataTable :value="products" class="p-datatable-striped"&gt;
@ -60,6 +63,31 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" class="p-datatable-striped">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity"></Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -74,5 +102,20 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products = data); this.productService.getProductsSmall().then(data => this.products = data);
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -27,6 +27,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products" :rowClass="rowClass"&gt; &lt;DataTable :value="products" :rowClass="rowClass"&gt;
@ -110,6 +113,37 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products" :rowClass="rowClass">
<Column field="code" header="Code"></Column>
<Column field="name" header="Name"></Column>
<Column field="category" header="Category"></Column>
<Column field="quantity" header="Quantity">
<template #body="slotProps">
<div :class="stockClass(slotProps.data)">
{{slotProps.data.quantity}}
</div>
</template>
</Column>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
@ -138,6 +172,56 @@ export default {
]; ];
} }
} }
}`,
style: `<style scoped lang="scss">
.outofstock {
font-weight: 700;
color: #FF5252;
text-decoration: line-through;
}
.lowstock {
font-weight: 700;
color: #FFA726;
}
.instock {
font-weight: 700;
color: #66BB6A;
}
::v-deep(.row-accessories) {
background-color: rgba(0,0,0,.15) !important;
}
</style>`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
rowClass(data) {
return data.category === 'Accessories' ? 'row-accessories': null;
},
stockClass(data) {
return [
{
'outofstock': data.quantity === 0,
'lowstock': data.quantity > 0 && data.quantity<10,
'instock': data.quantity > 10
}
];
}
},
components: {
LiveEditor
}
} }
</script> </script>

View File

@ -48,6 +48,9 @@
<div class="content-section documentation"> <div class="content-section documentation">
<TabView> <TabView>
<TabPanel header="Source"> <TabPanel header="Source">
<div class="p-d-flex p-jc-end">
<LiveEditor name="DataTableDemo" :sources="sources" service="ProductService" data="products-small" :components="['Column', 'Rating', 'Button']" />
</div>
<pre v-code> <pre v-code>
<code><template v-pre> <code><template v-pre>
&lt;DataTable :value="products"&gt; &lt;DataTable :value="products"&gt;
@ -135,7 +138,57 @@ export default {
<script> <script>
import ProductService from '../../service/ProductService'; import ProductService from '../../service/ProductService';
import LiveEditor from '../liveeditor/LiveEditor';
export default {
data() {
return {
products: null,
sources: {
'template': {
content: `<template>
<div class="layout-content">
<div class="content-section implementation">
<div class="card">
<DataTable :value="products">
<template #header>
<div class="table-header">
Products
<Button icon="pi pi-refresh" />
</div>
</template>
<Column field="name" header="Name"></Column>
<Column header="Image">
<template #body="slotProps">
<img src="https://www.primefaces.org/wp-content/uploads/2020/05/placeholder.png" :alt="slotProps.data.image" class="product-image" />
</template>
</Column>
<Column field="price" header="Price">
<template #body="slotProps">
{{formatCurrency(slotProps.data.price)}}
</template>
</Column>
<Column field="category" header="Category"></Column>
<Column field="rating" header="Reviews">
<template #body="slotProps">
<Rating :modelValue="slotProps.data.rating" :readonly="true" :cancel="false" />
</template>
</Column>
<Column header="Status">
<template #body="slotProps">
<span :class="'product-badge status-' + slotProps.data.inventoryStatus.toLowerCase()">{{slotProps.data.inventoryStatus}}</span>
</template>
</Column>
<template #footer>
In total there are {{products ? products.length : 0 }} products.
</template>
</DataTable>
</div>
</div>
</div>
</template>
<script>
import ProductService from '../service/ProductService';
export default { export default {
data() { data() {
return { return {
@ -154,6 +207,26 @@ export default {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'}); return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
} }
} }
}`
}
}
}
},
productService: null,
created() {
this.productService = new ProductService();
},
mounted() {
this.productService.getProductsSmall().then(data => this.products = data);
},
methods: {
formatCurrency(value) {
return value.toLocaleString('en-US', {style: 'currency', currency: 'USD'});
}
},
components: {
LiveEditor
}
} }
</script> </script>