├── README.md ├── addDelDatatable ├── addDelDatatable.css ├── addDelDatatable.html └── addDelDatatable.js └── example ├── example.html └── example.js /README.md: -------------------------------------------------------------------------------- 1 | # Add-Delete-Row-in-Lightning-Datatable-Lwc 2 | 3 | Simple LWC application to demonstrate the add, delete row to/from a lightning-data-table. Modal form to add a row in data-table. Open 'Edit' modal in Lightning Datatable, Delete Row Datatable, Add Row Datatable. 4 | 5 | ## Live playground example 6 | 7 | [Check out live example here](https://webcomponents.dev/edit/bkuc3TLe8cY4xJcoaleS/src/app.html) 8 | 9 | ## Steps to use the Component. 10 | 11 | 1. Create a new web component with the name addDelDatatable. 12 | 2. Copy and paste the code from addDelDatatable to your component's respective files addDelDatatable.js, addDelDatatable.html, addDelDatatable.css. 13 | 3. Use the below example code to implement the table. Replace the `Example` class name in JS with your desired parent component class name. 14 | 15 | #### Sample JS Code 16 | 17 | ``` 18 | import { LightningElement, track } from 'lwc'; 19 | 20 | export default class Example extends LightningElement { 21 | cols = [ 22 | { label: 'Name', fieldName: 'name', required: true }, 23 | { label: 'Phone', fieldName: 'phone', type: 'phone' }, 24 | ]; 25 | 26 | @track data = [ 27 | { uid: 1, name: 'Rahul', phone: '1234567890' }, 28 | { uid: 2, name: 'Arnav', phone: '1112223334' } 29 | ]; 30 | } 31 | ``` 32 | 33 | #### Sample HTML Markup 34 | 35 | ``` 36 | 37 | 38 | 39 | 40 | ``` 41 | 42 | #### How to Get the table data in parent component. 43 | 44 | Use below method to get updated table data from the `addDelDatatable` component into its parent. 45 | 46 | ``` 47 | handleGetData() { 48 | let dataFromChild = this.template.querySelector('c-add-del-datatable').data; 49 | console.log(`Got ${dataFromChild.length} record/s from the Child Component!`); 50 | console.log('data from child =>' + JSON.stringify(dataFromChild)); 51 | } 52 | ``` 53 | -------------------------------------------------------------------------------- /addDelDatatable/addDelDatatable.css: -------------------------------------------------------------------------------- 1 | h1 { 2 | color: rgb(0, 112, 210); 3 | } 4 | p { 5 | font-family: 'Salesforce Sans', Arial, sans-serif; 6 | color: rgb(62, 62, 60); 7 | } 8 | .app { 9 | background-color: #fafaf9; 10 | height: 100vh; 11 | overflow: scroll; 12 | } -------------------------------------------------------------------------------- /addDelDatatable/addDelDatatable.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 29 | 30 | 31 | 38 | Edit Row 42 | 43 | 47 | 48 | 53 | 61 | 71 | 72 | 82 | 83 | 84 | 85 | 86 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /addDelDatatable/addDelDatatable.js: -------------------------------------------------------------------------------- 1 | import {LightningElement, track, api} from "lwc"; 2 | 3 | export default class AddDelDatatable extends LightningElement { 4 | @track _columns = []; 5 | @track _data = []; 6 | @track _inputColumns; 7 | 8 | @api 9 | get columns() { 10 | return this._columns; 11 | } 12 | 13 | set columns(value) { 14 | this._columns = value; 15 | if (value) { 16 | let tempCols = [...value]; 17 | tempCols.push({type: "button-icon", typeAttributes: {iconName: "utility:delete", name: "delete", iconClass: "slds-icon-text-error"}, fixedWidth: 50}); 18 | tempCols.push({type: "button-icon", typeAttributes: {iconName: "utility:edit", name: "edit"}, fixedWidth: 50}); 19 | this._columns = tempCols; 20 | 21 | let colData = JSON.parse(JSON.stringify(value)); 22 | colData = colData.filter((column) => column.fieldName); 23 | colData.forEach((element) => { 24 | if (this.tempRow.hasOwnProperty(element.fieldName)) { 25 | element.displayValue = this.tempRow[element.fieldName]; 26 | } 27 | }); 28 | this._inputColumns = colData; 29 | } 30 | } 31 | 32 | @api 33 | get data() { 34 | return this._data; 35 | } 36 | 37 | set data(value) { 38 | this._data = value; 39 | } 40 | 41 | @track showModal; 42 | @track tempRow = {}; 43 | editMode = false; 44 | 45 | handleRowAction(event) { 46 | if (event.detail.action.name === "delete") { 47 | this.deleteSelectedRow(event.detail.row); 48 | } else if (event.detail.action.name === "edit") { 49 | this.editMode = true; 50 | this.openEditForm(event.detail.row); 51 | } 52 | } 53 | 54 | handleInputChange(event) { 55 | this.tempRow[event.target.name] = event.target.value; 56 | } 57 | 58 | deleteSelectedRow(deleteRow) { 59 | let newData = JSON.parse(JSON.stringify(this._data)); 60 | newData = newData.filter((row) => row.uid !== deleteRow.uid); 61 | 62 | // recalculate uids 63 | newData.forEach((element, index) => (element.uid = index + 1)); 64 | this._data = newData; 65 | } 66 | 67 | handleCancel() { 68 | this.tempRow = {}; 69 | this.showModal = false; 70 | this.editMode = false; 71 | this.editIndex = undefined; 72 | } 73 | 74 | handleAddRow() { 75 | this.tempRow = {}; 76 | // refresh inputColumn 77 | let tempInput = [...this._inputColumns]; 78 | tempInput.forEach((element) => (element.displayValue = undefined)); 79 | this._inputColumns = tempInput; 80 | this.showModal = true; 81 | } 82 | 83 | handleSave() { 84 | const allValid = [...this.template.querySelectorAll(`lightning-input`)].reduce((validSoFar, inputCmp) => { 85 | inputCmp.reportValidity(); 86 | return validSoFar && inputCmp.checkValidity(); 87 | }, true); 88 | 89 | if (!allValid) { 90 | return; 91 | } 92 | 93 | let newData = JSON.parse(JSON.stringify(this._data)); 94 | if (!this.editMode) { 95 | // you can use any unique and required field instead of 'uid'. 96 | //calculate ui 97 | this.tempRow.uid = this._data.length + 1; 98 | newData.push(this.tempRow); 99 | } else { 100 | newData[this.editIndex] = this.tempRow; 101 | this.editIndex = undefined; 102 | this.editMode = false; 103 | } 104 | this._data = newData; 105 | this.tempRow = {}; 106 | this.showModal = false; 107 | } 108 | 109 | openEditForm(editRow) { 110 | this.editIndex = this._data.findIndex((row) => row.uid === editRow.uid); 111 | this.tempRow = {...this._data[this.editIndex]}; 112 | this._inputColumns.forEach((element) => (element.displayValue = this.tempRow[element.fieldName])); 113 | this.showModal = true; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /example/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /example/example.js: -------------------------------------------------------------------------------- 1 | import {LightningElement, track} from "lwc"; 2 | const OPTIONS = [ 3 | {label: "New Customer", value: "New Customer"}, 4 | {label: "Old Customer", value: "Old Customer"}, 5 | {label: "Partner", value: "Partner"}, 6 | ]; 7 | export default class Example extends LightningElement { 8 | cols = [ 9 | {label: "Name", fieldName: "name", required: true}, 10 | {label: "Phone", fieldName: "phone", type: "phone", formPlaceholder: "+123.."}, 11 | {label: "Type", fieldName: "type", type: "text", isPicklist: true, options: OPTIONS}, 12 | ]; 13 | 14 | @track data = [ 15 | {uid: 1, name: "Rahul", phone: "1234567890", type: "New Customer"}, 16 | {uid: 2, name: "Arnav", phone: "1112223334", type: "Existing Customer"}, 17 | ]; 18 | 19 | handleGetData() { 20 | let dataFromChild = this.template.querySelector("c-add-del-datatable").data; 21 | console.log(`Got ${dataFromChild.length} record/s from the Child Component!`); 22 | console.log("data from child =>" + JSON.stringify(dataFromChild)); 23 | } 24 | } 25 | --------------------------------------------------------------------------------