0

I have implemented Custom type (custom component and custom data table) to show picklist values in LWC datatable. I have an event fired from this custom component and handling this event in my component. when pick list value is changed I want to update draft values to show 'save and cancel' and update table data. when trying to updated table data, I am receiving this error "[NoErrorObjectAvailable] Script error". Any pointers would help.

I have used below link for creating this componenet

https://live.playg.app/play/picklist-in-lightning-datatable

Here is my code:

dataTablepicklist.html

<template>
<div class="picklist-container">
<lightning-combobox name="picklist" label={label} value={value} placeholder={placeholder} options={options}
onchange={handleChange}></lightning-combobox> 

datatablePicklist.js

import { LightningElement,api } from 'lwc';

export default class DatatablePicklist extends LightningElement {

    @api label;
    @api placeholder;
    @api options;
    @api value;
    @api context;

    handleChange(event) {
        //show the selected value on UI
        this.value = event.detail.value;

        //fire event to send context and selected value to the data table
        this.dispatchEvent(new CustomEvent('picklistchanged', {
            composed: true,
            bubbles: true,
            detail: {
                picklistData: {context: this.context,value: this.value, placeholder: this.placeholder}
            }
        }
        ));
    }

}

picklist-template.html

<template>
    <c-datatable-picklist label={typeAttributes.label} value={typeAttributes.value}
    placeholder={typeAttributes.placeholder} options={typeAttributes.options} context={typeAttributes.context}>
</c-datatable-picklist>  
</template>

customDataTable.js

import LightningDatatable from 'lightning/datatable';
import DatatablePicklistTemplate from './picklist-template.html';
import {
    loadStyle
} from 'lightning/platformResourceLoader';
import CustomDataTableResource from '@salesforce/resourceUrl/CustomDataTable';

export default class CustomDataTable extends LightningDatatable {
    static customTypes = {
        picklist: {
            template: DatatablePicklistTemplate,
            typeAttributes: ['label', 'placeholder', 'options', 'value', 'context'],
        },

    };

    constructor() {
        super();
        Promise.all([
            loadStyle(this, CustomDataTableResource),
        ]).then(() => {})
    }

}

Custom component to show the custom datable with picklist

HTML file

    <template>
        <c-custom-data-table
                        key-field="id"
                        data={productData}
                        columns={columns}
                        hide-checkbox-column="true"
                        show-row-number-column="true"
                        min-column-width="75"
                        draft-values={draftValues}
                        oncellchange={handleCellChange}
                        onpicklistchanged={picklistChanged}
                        onrowaction={handleRowAction}
                         >
        </c-custom-data-table>
           
</template>

JS file-- I am getting error in updateDataValues method inside the for loop where I am trying to update loop variable with new picklist value

import { LightningElement,api,track } from 'lwc';
import createLineItems from '@salesforce/apex/AddProductsController.createLineItems';

const AUDIENCEOPTIONS = [
  {value: 'Parents', label: 'Parents'},
  {value: 'Kids', label: 'Kids'},
  {value: 'Teens', label: 'Teens'} 
];
const COLS = [
    {label: 'Product', fieldName: 'name',wrapText: true},
    {label:'Quantity',fieldName:'Quantity',editable: true},
    {label: 'Sales Metric', fieldName: 'salesMetric', type: 'picklist',wrapText: true,typeAttributes: {
      placeholder: 'Choose a value', options: [
        { label: 'CPA', value: 'CPA' },
        { label: 'CPC', value: 'CPC' },
        { label: 'CPCV', value: 'CPCV' },
        { label: 'CPI', value: 'CPI' },
        { label: 'CPM', value: 'CPM' },
        { label: 'CPVI', value: 'CPVI' },
        { label: 'Flat Rate', value: 'Flat Rate' },
        { label: 'CPE', value: 'CPE' },
      ]
      , value: { fieldName: 'salesMetric' } // default value for picklist
      , context: { fieldName: 'id' }
    // binding account Id with context variable to be returned back
  }},
    {label:'Sales Price',fieldName:'UnitPrice',editable: true,required:true},
   // {label:'Target Audience',fieldName: 'targetAudience',editable:true},
    {
      label:'Target Audience', fieldName: 'targetAudience', type: 'picklist',wrapText: true,typeAttributes: {
          placeholder: 'Choose Target Audience', options: [
            { label: 'Parents', value: 'Parents' },
            { label: 'Kids', value: 'Kids' },
            { label: 'Teens', value: 'Teens' }
          ] // list of all picklist options
          , value: { fieldName: 'targetAudience' } // default value for picklist
          , context: { fieldName: 'id' }
        // binding account Id with context variable to be returned back
      }
  },
    {label:'Target Age',fieldName: 'targetAge',type: 'picklist',wrapText: true,typeAttributes: {
      placeholder: 'Choose target Age', options:[ { label: '0-3', value: '0-3' },
      { label: '4-6', value: '4-6' },
      { label: '7-9', value: '7-9' },
      { label: '10-12', value: '10-12' },
      { label: '13-16', value: '13-16' },
      { label: 'NA', value: 'NA' },
      ] // list of all picklist options
      , value: { fieldName: 'targetAge'} // default value for picklist
      , context: { fieldName: 'id' }
    // binding account Id with context variable to be returned back
  }},
    {label:'Target Gender',fieldName:'targetGender',type: 'picklist',wrapText: true,typeAttributes: {
      placeholder: 'Choose Target Gender', options:[ { label: 'Boys', value: 'Boys' },
      { label: 'Girls', value: 'Girls' },
      { label: 'Boys & Girls', value: 'Boys & Girls' },
      ] // list of all picklist options
      , value: { fieldName: 'targetGender'} // default value for picklist
      , context: { fieldName: 'id' }
      , label:{fieldName:'label'}
    }
  },
    {label:'Device Type',fieldName:'deviceType'},
    {label:'KSV Price Plan',fieldName:'ksvPricePlan'},
    {label:'Start Date',fieldName: 'startDate',editable: true,type:'date',wrapText: true},
    {label:'End Date',fieldName: 'endDate',editable: true,type:'date',wrapText: true},
    {label:'Format',fieldName:'format'},
    {label:'Media Type',fieldName:'mediaType'},
    {label:'Delivery Type',fieldName:'deliveryType'},
    {
      type: 'button-icon',
      initialWidth: 75,
      typeAttributes: {
          iconName:'utility:copy',
          title: 'Copy'
      }
  },
    //{label:'Frequency Cap',fieldName:'FrequencyCap',editable:true},
    //{label:'Frequency Cap Period',fieldName:'FrequencyCapPeriod',editable:true}   
];

export default class EditAndSaveProducts extends LightningElement {

    @api recordId;

    @api productAttibutes;

    @track productData;

    columns = COLS;
    @track draftValues = [];


    
    @api 
    get products(){
        return this.productData;
      }
  
      set products(value){
          console.log(value);
        this.productData=value;
        console.log(JSON.stringify(this.productData));
      }

    get metricOptions() {
        return [
                 { label: 'CPA', value: 'CPA' },
                 { label: 'CPC', value: 'CPC' },
                 { label: 'CPCV', value: 'CPCV' },
                 { label: 'CPI', value: 'CPI' },
                 { label: 'CPM', value: 'CPM' },
                 { label: 'CPVI', value: 'CPVI' },
                 { label: 'Flat Rate', value: 'Flat Rate' },
                 { label: 'CPE', value: 'CPE' },
               ];
    }

    get deviceOptions(){
        return [
            { label: 'Connected TV', value: 'CConnected TV' },
            { label: 'Desktop', value: 'Desktop' },
            { label: 'Phone', value: 'Phone' },
            { label: 'Tablet', value: 'Tablet' },
          ];
    }

    

     /*handleSave(event){
      console.log('inside save');

 } */

 picklistChanged(event){
   event.stopPropagation(); 
   let dataRecieved = event.detail.picklistData;
   console.log('data Recieved'+ JSON.stringify(dataRecieved));
   if(dataRecieved.placeholder=='Choose Target Audience'){
   var updatedItem = { id: dataRecieved.context, targetAudience: dataRecieved.value};
   }
   else if(dataRecieved.placeholder=='Choose target Age'){
    var updatedItem = { id: dataRecieved.context, targetAge: dataRecieved.value};
    }

    else if(dataRecieved.placeholder=='Choose Target Gender'){
      var updatedItem = { id: dataRecieved.context, targetGender: dataRecieved.value};
      }
   console.log('picklist changed'+JSON.stringify(updatedItem));
   this.updateDraftValues(updatedItem);
   this.updateDataValues(updatedItem);

}


handleRowAction(event){
  console.log('inside row action');
  
}

handleCellChange(event) {
  console.log('inside cell change');
  this.updateDraftValues(event.detail.draftValues[0]);
  //this.updateDataValues(event.detail.draftValues[0])
}

updateDraftValues(updateItem) {
  console.log('inside draft values'+this.draftValues);
  let draftValueChanged = false;
  let copyDraftValues = [...this.draftValues];

  //store changed value to do operations
  //on save. This will enable inline editing &
  //show standard cancel & save button
  copyDraftValues.forEach(item => {
    console.log('inside loop');
      if (item.id === updateItem.id) {
          for (let field in updateItem) {
              item[field] = updateItem[field];
          }
          draftValueChanged = true;
      }
  });

  if (draftValueChanged) {
      this.draftValues = [...copyDraftValues];
  } else {
      this.draftValues = [...copyDraftValues, updateItem];
  }
  console.log('draft values'+ JSON.stringify(this.draftValues));
}

updateDataValues(updateItem) {
  console.log('inside update values'+JSON.stringify(updateItem));
  let copyData = [...this.productData];
  console.log('copydata'+JSON.stringify(copyData))
   copyData.forEach(item => {

      if (item.id === updateItem.id) {
        for (let field in updateItem) {
           console.log('line 257'+ item['Target Audience']);
            console.log('line 258'+updateItem[field]);
              item[field] = updateItem[field];
          } 
       }
  });

  //write changes back to original data
   this.productData = [...copyData];
  //console.log('data'+JSON.stringify(this.productData))
}

}

1 Answer 1

0

After research found that data was in read only mode. Fixed the issue by adding one more line as below in updateDataValues method

JSON.parse(JSON.stringify(copydata)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.