Mr.DevEng
Mr.DevEng

Reputation: 2421

Field Dependency implementation in Custom Picklist field type using LWC giving `[NoErrorObjectAvailable] Script error `

We are trying to implement field dependency in custom picklist field type with LWC. For this I created one LWC component to define custom lightning datatable. And I am using custom picklist fields which are dependent. Dependent fields are country and state. When changing country , automatically depended state need to load in custom picklist.

For this , From custom picklist onchange method, I am generating and sending one custom event to my main component by passing changed country value. But getting [NoErrorObjectAvailable] Script error with showing This page has an error. You might just need to refresh it. messsage while loading component,

Error Message

[NoErrorObjectAvailable] Script error. newErrorHandler()@https://static.lightning.force.com/ap24/auraFW/javascript/wyQWsVjjDIx-Xsqekbsbwg/aura_proddebug.js:67451:14 errorHandlerWrapper()@https://static.lightning.force.com/ap24/auraFW/javascript/wyQWsVjjDIx-Xsqekbsbwg/aura_proddebug.js:67467:25 dispatchEvent()@https://static.lightning.force.com/ap24/auraFW/javascript/wyQWsVjjDIx-Xsqekbsbwg/aura_proddebug.js:12804:25 LightningCombobox.dispatchEvent()@https://static.lightning.force.com/ap24/auraFW/javascript/wyQWsVjjDIx-Xsqekbsbwg/aura_proddebug.js:6928:18 LightningCombobox.value [as dispatchEvent]()@https://static.lightning.force.com/ap24/auraFW/javascript/wyQWsVjjDIx-Xsqekbsbwg/aura_proddebug.js:6172:48 LightningCombobox.handleSelect()@https://milletechdatasoftsystempvtl-

Error screen

enter image description here

My added .js code for sending controlling field format like the following,

     @wire(getObjectInfo, { objectApiName: myRegObject })
    objectInfo;

      @wire(getPicklistValues, 
        {recordTypeId: "$objectInfo.data.defaultRecordTypeId",fieldApiName: countryField})
    wireCountryPickList({ error, data }) 
        {
          if (data) {
              this.countryOptions = data.values;
          } 
          else if (error) {
              console.log(error);
          }
      }

      @wire(getPicklistValues, 
        {
          recordTypeId: "$objectInfo.data.defaultRecordTypeId",
          fieldApiName: stateField,
          controllingFieldValue: '$data.country__c'
        })
    wireStatePickList({ error, data }) 
        {
          if (data) {
              this.allStateOptions = data.values;
             
          } 
          else if (error) {
              console.log(error);
          }
      }

    @wire(getRegDetails, { pickList: '$countryOptions' })
    result(result){
      
      let sRObj = JSON.parse(JSON.stringify(result));
      this.sDetails = sRObj.data;    
        try
          {
            this.sDetails.forEach(ele => {
              ele.countryOptionsList = this.countryOptions;
              ele.stateOptionsList = this.allStateOptions;
              })
          }
        catch(err) {
            console.log(err.message);
        }
    } 


     handleControllingChange(event) {

         const selectedCountry = event.detail.value;
         console.log(selectedCountry);     
         this.stateOptions = this.allStateOptions
                            .filter(option => option.validFor.includes(selectedCountry));

         this.sDetails.forEach(ele => {
          ele.stateOptionsList = this.stateOptions;
          })
      
      }

And I am defining custom field in same .js file like the fllowing,

    const COLUMNS = [
    { 
      label : 'Country',
      fieldName: 'country__c',
      name : 'Country' ,
      placeholder : 'Choose Country',
      type: 'countryPicklist',
      typeAttributes: {
        value: { fieldName: 'country__c' },
        options: { fieldName: 'countryOptionsList' },
        },
      editable: true,
      context: { fieldName: 'Id' }
    },
    { 
      label : 'State',
      fieldName: 'state__c',
      name : 'State' ,
      placeholder : 'Choose State',
      type: 'statePicklist',
      typeAttributes: {
        value: { fieldName: 'state__c' },
        options: { fieldName: 'stateOptionsList' },
        },
      editable: true,
      context: { fieldName: 'Id' }
    },
    {
        type: 'button',
        typeAttributes: { label: 'Delete', name: 'delete' }
    }
    ]

And My custom picklist field created by extending LightningDatatable like the following,

    import LightningDatatable from 'lightning/datatable';

    import countryPicklist from './countryPicklist.html';
    import countryPicklistEdit from './countryPicklistEdit.html';
    import statePicklist from './statePicklist.html';
    import statePicklistEdit from './statePicklistEdit.html';


    export default class CustomDataTable extends LightningDatatable {

    static customTypes = {
        
         countryPicklist: {
            template: countryPicklistEdit,
            editTemplate: countryPicklist,
            standardCellLayout: true,
            typeAttributes: ['options', 'value']
        },
        statePicklist: {
            template: statePicklistEdit,
            editTemplate: statePicklist,
            standardCellLayout: true,
            typeAttributes: ['options', 'value']
        }
    };
    handleCountryChange(event) {
       
         const selectedCountry = event.detail.value;
    console.log(selectedCountry);
    this.dispatchEvent(new CustomEvent('countrychange', {detail: selectedCountry}));
    }
    }

Field Templates I am using for picklist custom type like the following, countryPicklistEdit.html,

       <template>
        <span class="slds-truncate" title={value}>{value}</span>
       </template>

countryPicklist.html,

      <template>
        <lightning-combobox 
        name='picklist' 
        label='Country'
        placeholder='Choose Country' 
        value={typeAttributes.value}
        options={typeAttributes.options}
        onchange={handleCountryChange}
        data-inputable="true"
        dropdown-alignment="auto"
        variant='label-hidden'>
       </lightning-combobox>
     </template>

And I am displaying data in my main html file like the following,

    <template>
      <c-custom-data-table
         key-field="Id" 
         data={sDetails} 
         show-row-number-column 
         onsave={handleSave}
         oncountrychange={handleControllingChange}
         hide-checkbox-column 
         columns={columns}
         onrowaction={handleRowAction}>
       </c-custom-data-table>
    </template>

Custom Object Definition already added field dependencies for Country to State fields. Problem here because of custom picklist.

Troubleshooted Way -

  1. At custom component .js file, to cross check whether event.detail has any problem or not by keeping one constant value to selectedCountry and passed by creating custom event. But not working.

  2. Cross checked the naming convention while creating and sending custom events from child to parent.

  1. Tested whether simple test messages using console.log statement. Even nothing printing. When changes country value to different value, immediately shows the error screen.

Problem I felt here with the onchange method defined for custom datatable , while changing country value to different value. Error page shows immediately after I changes country value. The html file is where I am defining onchange method is not my child component's html. Its additional html file added in the same directory and importing using import countryPicklist from './countryPicklist.html'; statement.

Updated Error in Console,

enter image description here

So can anyone suggest / guide to get a solution for this problem?

Upvotes: 2

Views: 1118

Answers (1)

Venkat
Venkat

Reputation: 29

can you try the below:

@wire(getPicklistValues, 
    {
      recordTypeId: "$objectInfo.data.defaultRecordTypeId",
      fieldApiName: minuteField
    })
wireMinutePickList({ error, data }) 
    {
      if (data) {
          this.minuteOptions = data.values;
//Getting the index of the controlling value as the single value can be dependant on multiple controller value
                let minuteOptionsControllerIndex = this.minuteOptions.controllerValues[this.hour__c];//assuming u have hour stored

let minuteOptionsTemp = [];
                this.minuteOptions.values.forEach((key) => {
                    for (let i = 0; i < key.validFor.length; i++) {
                        if (minuteOptionsControllerIndex === key.validFor[i]) {
                            minuteOptionsTemp.push({
                                label: key.label,
                                value: key.value
                            });
                        }
                    }
                });

this.minutesToDisplay = minuteOptionsTemp;
      } 
      else if (error) {
          console.log(error);
      }
  }

and the html can be as follows:

 <lightning-combobox name="Minute" label="Minute" class="validateField"
                                    options={minutesToDisplay}>
                                </lightning-combobox>

Upvotes: -1

Related Questions