Html injections for dependent picklists used in lightning web components in tables with edit

I am trying to build a dependent picklist dynamically within a table using Lightning Web component based on what is selected in the controlling picklist field. Html injections were possible in Aura framework however I am seeking help to understand how this could be achieved in LWC. I have also given a thought of using the datatable component (LWC) however don’t see any good document on how to use it for picklist and dependent picklists.

I have created two picklists on contact object one controlling and the other dependent.

The Apex class –

public with sharing class ContactController {

@AuraEnabled(cacheable=true)
public static List<wrapperClass> getContactList() {

    list<wrapperClass> returnwrapperClass = new list<wrapperClass>();

    list<contact> cont= [SELECT Id, Name, Title, Phone, Email, picklist1__c, picklist2__c FROM Contact where 
    picklist1__c != ''
    LIMIT 10];

    for(integer i = 0 ; i < cont.size();i++)
    {
      wrapperClass wc = new wrapperClass();
      wc.Contact = cont[i];
      wc.picklist1 = cont[i].id + '__pic1_'+ i;
      wc.picklist2 = wc.picklist1 + '___pic2_'+ i;
      returnwrapperClass.add(wc);
    }
   return returnwrapperClass;  }
 public class wrapperClass{
        @AuraEnabled public contact Contact{get;set;}
        @AuraEnabled public string picklist1{get;set;}
        @AuraEnabled public string picklist2 {get;set;}
    }}

I was partially successful achieving what I had set out for however still stuck where the UI is not able to stick the value selected in the combobox to the Contact record. (P.S : line 115 it should show an error when the code is executed) so the problem is picklist1__c and picklist2__c is associated with the contact object coming from the apex call / it is wired and I am unable to explicitely modify the content of Salesforce object from the Webcomponent framework – The .js file

import { LightningElement, wire , track } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import TYPE_FIELD from '@salesforce/schema/Contact.picklist1__c';
import TYPE_FIELD1 from '@salesforce/schema/Contact.picklist2__c';
import getContactList from '@salesforce/apex/ContactController.getContactList';
export default class WireGetPicklistValues extends LightningElement {
@track contacts = [];
@track picklistValues;
@track picklistValues2;
@track newobj = [];
@track tempcontact ;


@wire(getPicklistValues, {
    recordTypeId: '012B0000000gHiIIAU',
    fieldApiName: TYPE_FIELD,
})
getpicklistValues({error,data}){
    if (data) {
        this.picklistValues = data;
    } else if (error) {
        //
    }
}

@wire(getPicklistValues, {
    recordTypeId: '012B0000000gHiIIAU',
    fieldApiName: TYPE_FIELD1,
}) 
getpicklistValues2({error,data}){


    if (data) {
        this.picklistValues2 = data;
        // eslint-disable-next-line no-undef
        this.updateLink();
    } else if (error) {
        //this.error = error;
    }
}


@wire(getContactList) wiredcontacts({ error, data }) {

        if (data) {
            // eslint-disable-next-line no-undef
            this.updateContactContent(data);
        } else if (error) {
//   
        }
    } 
    updateLink(){
        var newlist = [];
        var obj = {};
        var x,y,transformed;
        // eslint-disable-next-line guard-for-in
        // eslint-disable-next-line guard-for-in
        for( x in this.picklistValues2.controllerValues)
        {


            for( y= 0; y < this.picklistValues2.values.length; y++)
            {
                    if(this.picklistValues2.values[y].validFor.includes(this.picklistValues2.controllerValues[x]))
                    {

                    obj = {"label": this.picklistValues2.values[y].label , "value" : this.picklistValues2.values[y].value };
                    newlist.push(obj);
                    }
            }   
            transformed = { "level" : x , "sublevel" : newlist};

            this.newobj.push(transformed);                   
        newlist = [];    
        } 


     }

    get options() {
       var i;
       // eslint-disable-next-line no-unused-vars
       var newObjs = [];
       var obj = {};
      // alert(this.picklistValues.values.length);
       for(i=0; i < this.picklistValues.values.length ; i++)
       {
         obj = {label : this.picklistValues.values[i].label , value: this.picklistValues.values[i].value}
         newObjs.push(obj);
       }
       return newObjs; 
    }


     // eslint-disable-next-line no-unused-vars
     handleChange(event) {


       var selectedName = event.target.id.split('-')[0];  

       var i,j; 
       for(i = 0 ; i < this.contacts.length ; i++ )
        {   

            if(this.contacts[i].picklist1 === selectedName)
            {  
                //alert("inside1");
               for( j = 0 ; j < this.newobj.length; j++)
               {
                   if( event.target.value === this.newobj[j].level)
                   {
                   this.contacts[i].pick2options = this.newobj[j].sublevel; 
                   console.log("this is the picklist value and dont know why it doesn't get set automatically :"+ this.contacts[i].Contact.picklist1__c );
                   console.log("this is the value coming in from the event.target.value which i m setting explicitely to the picklist : "+event.target.value);
                   this.contacts[i].Contact.picklist1__c =   event.target.value;  // ERROR!!!!!!         
                   }
               }
            }

        }
     }

     updateContactContent(data)
     {       
       var i,j;
       var obj;
       for(i=0;i < data.length; i++)
       {
        for(j=0 ; j< this.newobj.length;j++)
        {
            if(data[i].Contact.picklist1__c === this.newobj[j].level)
                    {
                        // eslint-disable-next-line no-new-object
                        obj  = new Object();
                        obj.Contact =  data[i].Contact;
                        obj.picklist1 = data[i].picklist1;
                        obj.picklist2 = data[i].picklist2;
                        obj.pick2options = this.newobj[j].sublevel;
                        this.contacts.push(obj);
                    }   
        }   


       }

     }

     handleClick(event)
     {

     }

}

The .html file is as follow with a few changes –

<template>

    <lightning-card title="WireGetPicklistValues" icon-name="custom:custom67">
        <table class="slds-table slds-table_bordered slds-table_col-bordered ">       
            <thead>
                    <tr>
                        <th style="width:10px;">Row #</th>
                        <th style="width:20px;">Picklist1</th>
                        <th style="width:20px;">Picklist2</th>
                    </tr>
            </thead>
            <tbody>


                    <template for:each={contacts} for:item="contact">
                      <tr key={contact.Contact.Name}>        
                            <td>
                                    {contact.Contact.Name}
                            </td>
                               <td>                                   
                             <lightning-combobox id ={contact.picklist1}
                                                    name="status"     
                                                    placeholder="Choose Status"
                                                    onchange={handleChange}
                                                    value={contact.Contact.picklist1__c}         
                                                    options={options}>
                             </lightning-combobox>

                            </td>



                            <td>

                              <lightning-combobox
                             id ={contact.picklist2}
                                    name="statussub"     
                                    placeholder="Choose Status"
                                value={contact.Contact.picklist2__c} 
                                options={contact.pick2options}>     

                            </lightning-combobox> 

                            </td>
                            </tr>    
                        </template>


                </tbody>
              </table>




    </lightning-card>

    <lightning-button
    variant="brand"
    label="Submit"
    onclick={handleClick}>
</lightning-button>

</template>

Unfortunate although I was successful to get dependent picklists in the table, I am unable to do a mass save. Any pointers in that direction would be wonderful..

Answer

The code is still large and the absence of formatting makes it very difficult to understand.

I believe you’re trying to:
a. Display a UI of a controlling (picklist1__c) and dependent (picklist2__c) picklist fields.
b. Update the UI for the dependent field based on the controlling field’s value.

If that’s accurate then I have good news!

Option 1

You can do this with zero Apex and Javascript.

<lightning-record-edit-form id="recordViewForm" record-id={recordId} object-api-name="Contact">
  <lightning-messages></lightning-messages>
  <lightning-input-field field-name="picklist1__c"></lightning-input-field>
  <lightning-input-field field-name="picklist2__c"></lightning-input-field>
  <lightning-button id="submit"
    type="submit"
    label="Update record"
    class="slds-m-top_medium">
  </lightning-button>
</lightning-record-edit-form>

See the docs for lightning-record-edit-form at https://developer.salesforce.com/docs/component-library/bundle/lightning-input-field/documentation
.

Bonus if you instead use static imports instead of the hard-coded strings. Eg replace picklist1__c in the template with a reference to a variable in the JS class that references import PICKLIST1_FIELD from '@salesforce/schema/Contact/picklist1__c';. See https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.data_wire_service_about. With static imports you get referential integrity including save-time validation of the field references.

Option 2

Use @wire(getPicklistValuesByRecordType, { objectApiName: 'Contact', recordTypeId: '012000000000000AAA' }) (or whatever record type is appropriate) to get metadata on the picklists which includes info on which are the controlling vs dependent picklist fields, and which values are available for which.

You can read more about that wire adapter at https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.reference_wire_adapters_picklist_values_record, which links to UIAPI’s resource and response body definitions.

Again you can use a static import for the object. Eg Contact becomes import CONTACT_OBJECT from '@salesforce/schema/Contact';.

Attribution
Source : Link , Question Author : shrita sharma , Answer Author : Kevin Venkiteswaran

Leave a Comment