Update editing demo

pull/1643/head
mertsincan 2021-10-04 12:48:04 +03:00
parent dcf60ef1a3
commit 467d6a26d9
2 changed files with 97 additions and 293 deletions

View File

@ -1122,17 +1122,16 @@ export default {
editor defines how the editing is implemented, below example demonstrates two cases. In the first example, simple v-model editors are utilized. This is pretty straightforward in most cases. editor defines how the editing is implemented, below example demonstrates two cases. In the first example, simple v-model editors are utilized. This is pretty straightforward in most cases.
On the other hand, second example is more advanced to consider validations and ability to revert values with the escape key.</p> On the other hand, second example is more advanced to consider validations and ability to revert values with the escape key.</p>
<pre v-code><code><template v-pre> <pre v-code><code><template v-pre>
&lt;h3&gt;Basic Cell Editing&lt;/h3&gt; &lt;h5&gt;Cell Editing&lt;/h5&gt;
&lt;p&gt;Simple editors with v-model.&lt;/p&gt; &lt;DataTable :value="cars" editMode="cell" @cell-edit-complete="onCellEditComplete"&gt;
&lt;DataTable :value="cars1" editMode="cell"&gt;
&lt;Column field="vin" header="Vin"&gt; &lt;Column field="vin" header="Vin"&gt;
&lt;template #editor="slotProps"&gt; &lt;template #editor="slotProps"&gt;
&lt;InputText v-model="slotProps.data[slotProps.column.field]" /&gt; &lt;InputText v-model="slotProps.data[slotProps.field]" /&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="year" header="Year"&gt; &lt;Column field="year" header="Year"&gt;
&lt;template #editor="slotProps"&gt; &lt;template #editor="slotProps"&gt;
&lt;InputText v-model="slotProps.data[slotProps.column.field]" /&gt; &lt;InputText v-model="slotProps.data[slotProps.field]" /&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="brand" header="Brand"&gt; &lt;Column field="brand" header="Brand"&gt;
@ -1149,17 +1148,7 @@ export default {
&lt;/Column&gt; &lt;/Column&gt;
&lt;Column field="color" header="Color"&gt; &lt;Column field="color" header="Color"&gt;
&lt;template #editor="slotProps"&gt; &lt;template #editor="slotProps"&gt;
&lt;InputText v-model="slotProps.data[slotProps.column.field]" /&gt; &lt;InputText v-model="slotProps.data[slotProps.field]" /&gt;
&lt;/template&gt;
&lt;/Column&gt;
&lt;/DataTable&gt;
&lt;h3&gt;Advanced Cell Editing&lt;/h3&gt;
&lt;p&gt;Custom implementation with validations, dynamic columns and reverting values with the escape key.&lt;/p&gt;
&lt;DataTable :value="cars2" editMode="cell" @cell-edit-complete="onCellEditComplete"&gt;
&lt;Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field"&gt;
&lt;template #editor="slotProps"&gt;
&lt;InputText :value="slotProps.data[slotProps.column.field]" @input="onCellEdit($event, slotProps)" /&gt;
&lt;/template&gt; &lt;/template&gt;
&lt;/Column&gt; &lt;/Column&gt;
&lt;/DataTable&gt; &lt;/DataTable&gt;
@ -1173,11 +1162,7 @@ import Vue from 'vue';
export default { export default {
data() { data() {
return { return {
cars1: null, cars: null,
cars2: null,
cars3: null,
editingCellRows: {},
columns: null,
brands: [ brands: [
{brand: 'Audi', value: 'Audi'}, {brand: 'Audi', value: 'Audi'},
{brand: 'BMW', value: 'BMW'}, {brand: 'BMW', value: 'BMW'},
@ -1194,45 +1179,27 @@ export default {
carService: null, carService: null,
created() { created() {
this.carService = new CarService(); this.carService = new CarService();
this.columns = [
{field: 'vin', header: 'Vin'},
{field: 'year', header: 'Year'},
{field: 'brand', header: 'Brand'},
{field: 'color', header: 'Color'}
];
}, },
methods: { methods: {
onCellEditComplete(event) { onCellEditComplete(event) {
if (!this.editingCellRows[event.index]) { let { data, newValue, field } = event;
return;
}
const editingCellValue = this.editingCellRows[event.index][event.field];
switch (event.field) { switch (event.field) {
case 'year': case 'year':
if (this.isPositiveInteger(editingCellValue)) if (this.isPositiveInteger(newValue))
Vue.set(this.cars2, event.index, this.editingCellRows[event.index]); data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
default: default:
if (editingCellValue.trim().length > 0) if (newValue.trim().length > 0)
Vue.set(this.cars2, event.index, this.editingCellRows[event.index]); data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
} }
}, },
onCellEdit(newValue, props) {
if (!this.editingCellRows[props.index]) {
this.editingCellRows[props.index] = {...props.data};
}
this.editingCellRows[props.index][props.column.field] = newValue;
},
isPositiveInteger(val) { isPositiveInteger(val) {
let str = String(val); let str = String(val);
str = str.trim(); str = str.trim();
@ -1245,8 +1212,7 @@ export default {
} }
}, },
mounted() { mounted() {
this.carService.getCarsSmall().then(data => this.cars1 = data); this.carService.getCarsSmall().then(data => this.cars = data);
this.carService.getCarsSmall().then(data => this.cars2 = data);
} }
} }
@ -1256,8 +1222,7 @@ export default {
since <i>editingRows</i> is two-way binding enabled, you may use it to initially display one or more rows in editing more or programmatically toggle row editing.</p> since <i>editingRows</i> is two-way binding enabled, you may use it to initially display one or more rows in editing more or programmatically toggle row editing.</p>
<pre v-code><code><template v-pre> <pre v-code><code><template v-pre>
&lt;h3&gt;Row Editing&lt;/h3&gt; &lt;h3&gt;Row Editing&lt;/h3&gt;
&lt;DataTable :value="cars" editMode="row" dataKey="vin" v-model:editingRows="editingRows" &lt;DataTable :value="cars" editMode="row" dataKey="vin" v-model:editingRows="editingRows" @row-edit-save="onRowEditSave"&gt;
@row-edit-init="onRowEditInit" @row-edit-cancel="onRowEditCancel"&gt;
&lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt; &lt;Column field="vin" header="Vin"&gt;&lt;/Column&gt;
&lt;Column field="year" header="Year"&gt; &lt;Column field="year" header="Year"&gt;
&lt;template #editor="slotProps"&gt; &lt;template #editor="slotProps"&gt;
@ -1291,19 +1256,15 @@ export default {
} }
}, },
carService: null, carService: null,
originalRows: null,
created() { created() {
this.carService = new CarService(); this.carService = new CarService();
this.originalRows = {};
}, },
methods: { methods: {
onRowEditInit(event) { onRowEditSave(event) {
this.originalRows[event.index] = {...this.cars3[event.index]}; let { newData, index } = event;
this.cars[index] = newData;
}, },
onRowEditCancel(event) {
Vue.set(this.cars3, event.index, this.originalRows[event.index]);
}
}, },
mounted() { mounted() {
this.carService.getCarsSmall().then(data => this.cars = data); this.carService.getCarsSmall().then(data => this.cars = data);

View File

@ -12,46 +12,12 @@
<div class="content-section implementation p-fluid"> <div class="content-section implementation p-fluid">
<div class="card"> <div class="card">
<h5>Basic Cell Editing</h5> <h5>Cell Editing</h5>
<p>Simple editors with v-model.</p> <p>Validations, dynamic columns and reverting values with the escape key.</p>
<DataTable :value="products1" editMode="cell" class="editable-cells-table" responsiveLayout="scroll"> <DataTable :value="products1" editMode="cell" @cell-edit-complete="onCellEditComplete" class="editable-cells-table" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="name" header="Name" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" style="width:25%">
<template #editor="slotProps">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="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" style="width:25%">
<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" responsiveLayout="scroll">
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%"> <Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText :modelValue="slotProps.data[slotProps.column.props.field]" @update:modelValue="onCellEdit($event, slotProps)" /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@ -59,21 +25,20 @@
<div class="card"> <div class="card">
<h5>Row Editing</h5> <h5>Row Editing</h5>
<DataTable :value="products3" editMode="row" dataKey="id" v-model:editingRows="editingRows" <DataTable :value="products2" editMode="row" dataKey="id" v-model:editingRows="editingRows" @row-edit-save="onRowEditSave" responsiveLayout="scroll">
@row-edit-init="onRowEditInit" @row-edit-cancel="onRowEditCancel" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:20%"> <Column field="code" header="Code" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" autofocus /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
<Column field="name" header="Name" style="width:20%"> <Column field="name" header="Name" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column field="inventoryStatus" header="Status" style="width:20%"> <Column field="inventoryStatus" header="Status" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status"> <Dropdown v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status">
<template #option="slotProps"> <template #option="slotProps">
<span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span> <span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span>
</template> </template>
@ -84,8 +49,8 @@
</template> </template>
</Column> </Column>
<Column field="price" header="Price" style="width:20%"> <Column field="price" header="Price" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column :rowEditor="true" style="width:10%; min-width:8rem" bodyStyle="text-align:center"></Column> <Column :rowEditor="true" style="width:10%; min-width:8rem" bodyStyle="text-align:center"></Column>
@ -103,12 +68,10 @@ import ProductService from '../../service/ProductService';
export default { export default {
data() { data() {
return { return {
editingCellRows: {},
editingRows: [], editingRows: [],
columns: null, columns: null,
products1: null, products1: null,
products2: null, products2: null,
products3: null,
statuses: [ statuses: [
{label: 'In Stock', value: 'INSTOCK'}, {label: 'In Stock', value: 'INSTOCK'},
{label: 'Low Stock', value: 'LOWSTOCK'}, {label: 'Low Stock', value: 'LOWSTOCK'},
@ -121,46 +84,12 @@ export default {
<template> <template>
<div class="p-fluid"> <div class="p-fluid">
<div class="card"> <div class="card">
<h5>Basic Cell Editing</h5> <h5>Cell Editing</h5>
<p>Simple editors with v-model.</p> <p>Validations, dynamic columns and reverting values with the escape key.</p>
<DataTable :value="products1" editMode="cell" class="editable-cells-table" responsiveLayout="scroll"> <DataTable :value="products1" editMode="cell" @cell-edit-complete="onCellEditComplete" class="editable-cells-table" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="name" header="Name" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" style="width:25%">
<template #editor="slotProps">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="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" style="width:25%">
<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" @cellEditComplete="onCellEditComplete" class="editable-cells-table" responsiveLayout="scroll">
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%"> <Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText :modelValue="slotProps.data[slotProps.column.props.field]" @update:modelValue="onCellEdit($event, slotProps)" /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@ -168,21 +97,20 @@ export default {
<div class="card"> <div class="card">
<h5>Row Editing</h5> <h5>Row Editing</h5>
<DataTable :value="products3" editMode="row" dataKey="id" v-model:editingRows="editingRows" <DataTable :value="products2" editMode="row" dataKey="id" v-model:editingRows="editingRows" @row-edit-save="onRowEditSave" responsiveLayout="scroll">
@rowEditInit="onRowEditInit" @rowEditCancel="onRowEditCancel" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:20%"> <Column field="code" header="Code" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" autofocus /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
<Column field="name" header="Name" style="width:20%"> <Column field="name" header="Name" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column field="inventoryStatus" header="Status" style="width:20%"> <Column field="inventoryStatus" header="Status" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status"> <Dropdown v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status">
<template #option="slotProps"> <template #option="slotProps">
<span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span> <span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span>
</template> </template>
@ -193,14 +121,14 @@ export default {
</template> </template>
</Column> </Column>
<Column field="price" header="Price" style="width:20%"> <Column field="price" header="Price" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column :rowEditor="true" style="width: 10%; min-width:8rem" bodyStyle="text-align:center"></Column> <Column :rowEditor="true" style="width:10%; min-width:8rem" bodyStyle="text-align:center"></Column>
</DataTable> </DataTable>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
@ -209,12 +137,10 @@ import ProductService from './service/ProductService';
export default { export default {
data() { data() {
return { return {
editingCellRows: {},
editingRows: [], editingRows: [],
columns: null, columns: null,
products1: null, products1: null,
products2: null, products2: null,
products3: null,
statuses: [ statuses: [
{label: 'In Stock', value: 'INSTOCK'}, {label: 'In Stock', value: 'INSTOCK'},
{label: 'Low Stock', value: 'LOWSTOCK'}, {label: 'Low Stock', value: 'LOWSTOCK'},
@ -222,7 +148,6 @@ export default {
] ]
} }
}, },
originalRows: null,
productService: null, productService: null,
created() { created() {
this.productService = new ProductService(); this.productService = new ProductService();
@ -233,41 +158,28 @@ export default {
{field: 'quantity', header: 'Quantity'}, {field: 'quantity', header: 'Quantity'},
{field: 'price', header: 'Price'} {field: 'price', header: 'Price'}
]; ];
this.originalRows = {};
}, },
methods: { methods: {
onCellEditComplete(event) { onCellEditComplete(event) {
if (!this.editingCellRows[event.index]) { let { data, newValue, field } = event;
return;
}
const editingCellValue = this.editingCellRows[event.index][event.field]; switch (field) {
switch (event.field) {
case 'quantity': case 'quantity':
case 'price': case 'price':
if (this.isPositiveInteger(editingCellValue)) if (this.isPositiveInteger(newValue))
this.products2[event.index] = {...this.editingCellRows[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
default: default:
if (editingCellValue.trim().length > 0) if (newValue.trim().length > 0)
this.products2[event.index] = {...this.editingCellRows[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; 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) { isPositiveInteger(val) {
let str = String(val); let str = String(val);
str = str.trim(); str = str.trim();
@ -278,11 +190,10 @@ export default {
var n = Math.floor(Number(str)); var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0; return n !== Infinity && String(n) === str && n >= 0;
}, },
onRowEditInit(event) { onRowEditSave(event) {
this.originalRows[event.index] = {...this.products3[event.index]}; let { newData, index } = event;
},
onRowEditCancel(event) { this.products2[index] = newData;
this.products3[event.index] = this.originalRows[event.index];
}, },
getStatusLabel(status) { getStatusLabel(status) {
switch(status) { switch(status) {
@ -303,7 +214,6 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products1 = data); this.productService.getProductsSmall().then(data => this.products1 = data);
this.productService.getProductsSmall().then(data => this.products2 = data); this.productService.getProductsSmall().then(data => this.products2 = data);
this.productService.getProductsSmall().then(data => this.products3 = data);
} }
} }
<\\/script> <\\/script>
@ -321,46 +231,12 @@ export default {
<template> <template>
<div class="p-fluid"> <div class="p-fluid">
<div class="card"> <div class="card">
<h5>Basic Cell Editing</h5> <h5>Cell Editing</h5>
<p>Simple editors with v-model.</p> <p>Validations, dynamic columns and reverting values with the escape key.</p>
<DataTable :value="products1" editMode="cell" class="editable-cells-table" responsiveLayout="scroll"> <DataTable :value="products1" editMode="cell" @cell-edit-complete="onCellEditComplete" class="editable-cells-table" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="name" header="Name" style="width:25%">
<template #editor="slotProps">
<InputText v-model="slotProps.data[slotProps.column.props.field]" />
</template>
</Column>
<Column field="inventoryStatus" header="Status" style="width:25%">
<template #editor="slotProps">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="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" style="width:25%">
<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" @cellEditComplete="onCellEditComplete" class="editable-cells-table" responsiveLayout="scroll">
<Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%"> <Column v-for="col of columns" :field="col.field" :header="col.header" :key="col.field" style="width:25%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText :modelValue="slotProps.data[slotProps.column.props.field]" @update:modelValue="onCellEdit($event, slotProps)" /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
</DataTable> </DataTable>
@ -368,21 +244,20 @@ export default {
<div class="card"> <div class="card">
<h5>Row Editing</h5> <h5>Row Editing</h5>
<DataTable :value="products3" editMode="row" dataKey="id" v-model:editingRows="editingRows" <DataTable :value="products2" editMode="row" dataKey="id" v-model:editingRows="editingRows" @row-edit-save="onRowEditSave" responsiveLayout="scroll">
@rowEditInit="onRowEditInit" @rowEditCancel="onRowEditCancel" responsiveLayout="scroll">
<Column field="code" header="Code" style="width:20%"> <Column field="code" header="Code" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" autofocus /> <InputText v-model="data[field]" autofocus />
</template> </template>
</Column> </Column>
<Column field="name" header="Name" style="width:20%"> <Column field="name" header="Name" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column field="inventoryStatus" header="Status" style="width:20%"> <Column field="inventoryStatus" header="Status" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<Dropdown v-model="slotProps.data['inventoryStatus']" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status"> <Dropdown v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status">
<template #option="slotProps"> <template #option="slotProps">
<span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span> <span :class="'product-badge status-' + slotProps.option.value.toLowerCase()">{{slotProps.option.label}}</span>
</template> </template>
@ -393,14 +268,14 @@ export default {
</template> </template>
</Column> </Column>
<Column field="price" header="Price" style="width:20%"> <Column field="price" header="Price" style="width:20%">
<template #editor="slotProps"> <template #editor="{ data, field }">
<InputText v-model="slotProps.data[slotProps.column.props.field]" /> <InputText v-model="data[field]" />
</template> </template>
</Column> </Column>
<Column :rowEditor="true" style="width: 10%; min-width:8rem" bodyStyle="text-align:center"></Column> <Column :rowEditor="true" style="width:10%; min-width:8rem" bodyStyle="text-align:center"></Column>
</DataTable> </DataTable>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
@ -412,11 +287,9 @@ export default {
onMounted(() => { onMounted(() => {
productService.value.getProductsSmall().then(data => products1.value = data); productService.value.getProductsSmall().then(data => products1.value = data);
productService.value.getProductsSmall().then(data => products2.value = data); productService.value.getProductsSmall().then(data => products2.value = data);
productService.value.getProductsSmall().then(data => products3.value = data); });
})
const productService = ref(new ProductService()); const productService = ref(new ProductService());
const editingCellRows = ref({});
const editingRows = ref([]); const editingRows = ref([]);
const columns = ref([ const columns = ref([
{field: 'code', header: 'Code'}, {field: 'code', header: 'Code'},
@ -426,8 +299,6 @@ export default {
]); ]);
const products1 = ref(null); const products1 = ref(null);
const products2 = ref(null); const products2 = ref(null);
const products3 = ref(null);
const originalRows = ref({});
const statuses = ref([ const statuses = ref([
{label: 'In Stock', value: 'INSTOCK'}, {label: 'In Stock', value: 'INSTOCK'},
{label: 'Low Stock', value: 'LOWSTOCK'}, {label: 'Low Stock', value: 'LOWSTOCK'},
@ -435,36 +306,25 @@ export default {
]); ]);
const onCellEditComplete = (event) => { const onCellEditComplete = (event) => {
if (!editingCellRows.value[event.index]) { let { data, newValue, field } = event;
return;
}
const editingCellValue = editingCellRows.value[event.index][event.field]; switch (field) {
switch (event.field) {
case 'quantity': case 'quantity':
case 'price': case 'price':
if (isPositiveInteger(editingCellValue)) if (isPositiveInteger(newValue))
products2.value[event.index] = {...editingCellRows.value[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
default: default:
if (editingCellValue.trim().length > 0) if (newValue.trim().length > 0)
products2.value[event.index] = {...editingCellRows.value[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
} }
}; };
const onCellEdit = (newValue, props) => {
if (!editingCellRows.value[props.index]) {
editingCellRows.value[props.index] = {...props.data};
}
editingCellRows.value[props.index][props.column.props.field] = newValue;
};
const isPositiveInteger = (val) => { const isPositiveInteger = (val) => {
let str = String(val); let str = String(val);
str = str.trim(); str = str.trim();
@ -475,11 +335,10 @@ export default {
var n = Math.floor(Number(str)); var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0; return n !== Infinity && String(n) === str && n >= 0;
}; };
const onRowEditInit = (event) => { const onRowEditSave = (event) => {
originalRows.value[event.index] = {...products3.value[event.index]}; let { newData, index } = event;
};
const onRowEditCancel = (event) => { products2[index] = newData;
products3.value[event.index] = originalRows.value[event.index];
}; };
const getStatusLabel = (status) => { const getStatusLabel = (status) => {
switch(status) { switch(status) {
@ -497,8 +356,8 @@ export default {
} }
}; };
return { productService, editingCellRows, editingRows, columns, products1, products2, products3, originalRows, statuses, onCellEditComplete, return { productService, editingRows, columns, products1, products2, statuses, onCellEditComplete,
onCellEdit, isPositiveInteger, onRowEditInit, onRowEditCancel, getStatusLabel } isPositiveInteger, onRowEditSave, getStatusLabel }
} }
} }
<\\/script> <\\/script>
@ -513,7 +372,6 @@ export default {
} }
} }
}, },
originalRows: null,
productService: null, productService: null,
created() { created() {
this.productService = new ProductService(); this.productService = new ProductService();
@ -524,41 +382,28 @@ export default {
{field: 'quantity', header: 'Quantity'}, {field: 'quantity', header: 'Quantity'},
{field: 'price', header: 'Price'} {field: 'price', header: 'Price'}
]; ];
this.originalRows = {};
}, },
methods: { methods: {
onCellEditComplete(event) { onCellEditComplete(event) {
if (!this.editingCellRows[event.index]) { let { data, newValue, field } = event;
return;
}
const editingCellValue = this.editingCellRows[event.index][event.field]; switch (field) {
switch (event.field) {
case 'quantity': case 'quantity':
case 'price': case 'price':
if (this.isPositiveInteger(editingCellValue)) if (this.isPositiveInteger(newValue))
this.products2[event.index] = {...this.editingCellRows[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; break;
default: default:
if (editingCellValue.trim().length > 0) if (newValue.trim().length > 0)
this.products2[event.index] = {...this.editingCellRows[event.index]}; data[field] = newValue;
else else
event.preventDefault(); event.preventDefault();
break; 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) { isPositiveInteger(val) {
let str = String(val); let str = String(val);
str = str.trim(); str = str.trim();
@ -569,11 +414,10 @@ export default {
var n = Math.floor(Number(str)); var n = Math.floor(Number(str));
return n !== Infinity && String(n) === str && n >= 0; return n !== Infinity && String(n) === str && n >= 0;
}, },
onRowEditInit(event) { onRowEditSave(event) {
this.originalRows[event.index] = {...this.products3[event.index]}; let { newData, index } = event;
},
onRowEditCancel(event) { this.products2[index] = newData;
this.products3[event.index] = this.originalRows[event.index];
}, },
getStatusLabel(status) { getStatusLabel(status) {
switch(status) { switch(status) {
@ -594,7 +438,6 @@ export default {
mounted() { mounted() {
this.productService.getProductsSmall().then(data => this.products1 = data); this.productService.getProductsSmall().then(data => this.products1 = data);
this.productService.getProductsSmall().then(data => this.products2 = data); this.productService.getProductsSmall().then(data => this.products2 = data);
this.productService.getProductsSmall().then(data => this.products3 = data);
} }
} }
</script> </script>
@ -604,4 +447,4 @@ export default {
padding-top: 0; padding-top: 0;
padding-bottom: 0; padding-bottom: 0;
} }
</style> </style>