<template> <DocSectionText v-bind="$attrs"> <p> Row editing is configured with setting <i>editMode</i> as <i>row</i> and defining <i>editingRows</i> with the v-model directive to hold the reference of the editing rows. Similarly with cell edit mode, defining input elements with <i>editor</i> slot of a Column and implementing <i>row-edit-save</i> are necessary to update the state. The column to control the editing state should have <i>editor</i> templating applied. </p> </DocSectionText> <DeferredDemo @load="loadDemoData"> <div class="card"> <DataTable v-model:editingRows="editingRows" :value="products" editMode="row" dataKey="id" @row-edit-save="onRowEditSave" :pt="{ table: { style: 'min-width: 50rem' }, column: { bodycell: ({ state }) => ({ style: state['d_editing'] && 'padding-top: 0.75rem; padding-bottom: 0.75rem' }) } }" > <Column field="code" header="Code" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="name" header="Name" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="inventoryStatus" header="Status" style="width: 20%"> <template #editor="{ data, field }"> <Select v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status" fluid> <template #option="slotProps"> <Tag :value="slotProps.option.value" :severity="getStatusLabel(slotProps.option.value)" /> </template> </Select> </template> <template #body="slotProps"> <Tag :value="slotProps.data.inventoryStatus" :severity="getStatusLabel(slotProps.data.inventoryStatus)" /> </template> </Column> <Column field="price" header="Price" style="width: 20%"> <template #body="{ data, field }"> {{ formatCurrency(data[field]) }} </template> <template #editor="{ data, field }"> <InputNumber v-model="data[field]" mode="currency" currency="USD" locale="en-US" fluid /> </template> </Column> <Column :rowEditor="true" style="width: 10%; min-width: 8rem" bodyStyle="text-align:center"></Column> </DataTable> </div> </DeferredDemo> <DocSectionCode :code="code" :service="['ProductService']" :dependencies="{ sass: '1.45.0', 'sass-loader': '8.0.2' }" /> </template> <script> import { ProductService } from '@/service/ProductService'; export default { data() { return { products: null, editingRows: [], statuses: [ { label: 'In Stock', value: 'INSTOCK' }, { label: 'Low Stock', value: 'LOWSTOCK' }, { label: 'Out of Stock', value: 'OUTOFSTOCK' } ], code: { basic: ` <DataTable v-model:editingRows="editingRows" :value="products" editMode="row" dataKey="id" @row-edit-save="onRowEditSave" :pt="{ table: { style: 'min-width: 50rem' }, column: { bodycell: ({ state }) => ({ style: state['d_editing']&&'padding-top: 0.75rem; padding-bottom: 0.75rem' }) } }" > <Column field="code" header="Code" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" /> </template> </Column> <Column field="name" header="Name" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="inventoryStatus" header="Status" style="width: 20%"> <template #editor="{ data, field }"> <Select v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status" fluid> <template #option="slotProps"> <Tag :value="slotProps.option.value" :severity="getStatusLabel(slotProps.option.value)" /> </template> </Select> </template> <template #body="slotProps"> <Tag :value="slotProps.data.inventoryStatus" :severity="getStatusLabel(slotProps.data.inventoryStatus)" /> </template> </Column> <Column field="price" header="Price" style="width: 20%"> <template #body="{ data, field }"> {{ formatCurrency(data[field]) }} </template> <template #editor="{ data, field }"> <InputNumber v-model="data[field]" mode="currency" currency="USD" locale="en-US" fluid /> </template> </Column> <Column :rowEditor="true" style="width: 10%; min-width: 8rem" bodyStyle="text-align:center"></Column> </DataTable> `, options: ` <template> <div class="card"> <DataTable v-model:editingRows="editingRows" :value="products" editMode="row" dataKey="id" @row-edit-save="onRowEditSave" :pt="{ table: { style: 'min-width: 50rem' }, column: { bodycell: ({ state }) => ({ style: state['d_editing']&&'padding-top: 0.75rem; padding-bottom: 0.75rem' }) } }" > <Column field="code" header="Code" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="name" header="Name" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="inventoryStatus" header="Status" style="width: 20%"> <template #editor="{ data, field }"> <Select v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status" fluid> <template #option="slotProps"> <Tag :value="slotProps.option.value" :severity="getStatusLabel(slotProps.option.value)" /> </template> </Select> </template> <template #body="slotProps"> <Tag :value="slotProps.data.inventoryStatus" :severity="getStatusLabel(slotProps.data.inventoryStatus)" /> </template> </Column> <Column field="price" header="Price" style="width: 20%"> <template #body="{ data, field }"> {{ formatCurrency(data[field]) }} </template> <template #editor="{ data, field }"> <InputNumber v-model="data[field]" mode="currency" currency="USD" locale="en-US" fluid /> </template> </Column> <Column :rowEditor="true" style="width: 10%; min-width: 8rem" bodyStyle="text-align:center"></Column> </DataTable> </div> </template> <script> import { ProductService } from '@/service/ProductService'; export default { data() { return { products: null, editingRows: [], statuses: [ { label: 'In Stock', value: 'INSTOCK' }, { label: 'Low Stock', value: 'LOWSTOCK' }, { label: 'Out of Stock', value: 'OUTOFSTOCK' } ] }; }, mounted() { ProductService.getProductsMini().then((data) => (this.products = data)); }, methods: { onRowEditSave(event) { let { newData, index } = event; this.products[index] = newData; }, getStatusLabel(status) { switch (status) { case 'INSTOCK': return 'success'; case 'LOWSTOCK': return 'warn'; case 'OUTOFSTOCK': return 'danger'; default: return null; } }, formatCurrency(value) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value); } } }; <\/script> `, composition: ` <template> <div class="card"> <DataTable v-model:editingRows="editingRows" :value="products" editMode="row" dataKey="id" @row-edit-save="onRowEditSave" :pt="{ table: { style: 'min-width: 50rem' }, column: { bodycell: ({ state }) => ({ style: state['d_editing']&&'padding-top: 0.75rem; padding-bottom: 0.75rem' }) } }" > <Column field="code" header="Code" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="name" header="Name" style="width: 20%"> <template #editor="{ data, field }"> <InputText v-model="data[field]" fluid /> </template> </Column> <Column field="inventoryStatus" header="Status" style="width: 20%"> <template #editor="{ data, field }"> <Select v-model="data[field]" :options="statuses" optionLabel="label" optionValue="value" placeholder="Select a Status" fluid> <template #option="slotProps"> <Tag :value="slotProps.option.value" :severity="getStatusLabel(slotProps.option.value)" /> </template> </Select> </template> <template #body="slotProps"> <Tag :value="slotProps.data.inventoryStatus" :severity="getStatusLabel(slotProps.data.inventoryStatus)" /> </template> </Column> <Column field="price" header="Price" style="width: 20%"> <template #body="{ data, field }"> {{ formatCurrency(data[field]) }} </template> <template #editor="{ data, field }"> <InputNumber v-model="data[field]" mode="currency" currency="USD" locale="en-US" fluid /> </template> </Column> <Column :rowEditor="true" style="width: 10%; min-width: 8rem" bodyStyle="text-align:center"></Column> </DataTable> </div> </template> <script setup> import { ref, onMounted } from 'vue'; import { ProductService } from '@/service/ProductService'; const products = ref(); const editingRows = ref([]); const statuses = ref([ { label: 'In Stock', value: 'INSTOCK' }, { label: 'Low Stock', value: 'LOWSTOCK' }, { label: 'Out of Stock', value: 'OUTOFSTOCK' } ]); onMounted(() => { ProductService.getProductsMini().then((data) => (products.value = data)); }); const onRowEditSave = (event) => { let { newData, index } = event; products.value[index] = newData; }; const getStatusLabel = (status) => { switch (status) { case 'INSTOCK': return 'success'; case 'LOWSTOCK': return 'warn'; case 'OUTOFSTOCK': return 'danger'; default: return null; } }; const formatCurrency = (value) => { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value); } <\/script> `, data: ` { id: '1000', code: 'f230fh0g3', name: 'Bamboo Watch', description: 'Product Description', image: 'bamboo-watch.jpg', price: 65, category: 'Accessories', quantity: 24, inventoryStatus: 'INSTOCK', rating: 5 }, ... ` } }; }, methods: { loadDemoData() { ProductService.getProductsMini().then((data) => (this.products = data)); }, onRowEditSave(event) { let { newData, index } = event; this.products[index] = newData; }, getStatusLabel(status) { switch (status) { case 'INSTOCK': return 'success'; case 'LOWSTOCK': return 'warn'; case 'OUTOFSTOCK': return 'danger'; default: return null; } }, formatCurrency(value) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(value); } } }; </script>