TransWikia.com

Creating custom dependent picklist field in LWC

Salesforce Asked by SFDC IN on September 30, 2020

I have a picklist field which I am fetching using wire. Now the scenario is I have to fetch all the records of the selected picklist value and show the values of one of the field in records in another picklist.

Say I have Type as one Picklist then based on Type value, I need to show the Account Names in other picklist field where Type value is the selected Type.

I have written the below code till now but when I select the Type value for the 1st time it gives me "Cannot read property of length error" and when I select it for the 2nd time it doesn’t give me any error but can’t get Account Name values in the dependent picklist field

HTML:

<lightning-layout-item size="10" padding="horizontal-medium">
                    <lightning-combobox class="" options={typeValues} dropdown-alignment="auto" 
                       label="Type"
                        placeholder="--Select Type--" value={typeSelected} onchange= 
                              {handleTypeChange}
                        required>
                    </lightning-combobox>
</lightning-layout-item>
<lightning-layout-item size="5" padding="horizontal-medium">
                <lightning-combobox class="" options={accountNames} dropdown-alignment="auto" 
                                   label="Account"
                    placeholder="--Select Account--" value={accountSelected} onchange= 
                             {handleNameChange}
                    required disabled={isTypeSelected}>
                </lightning-combobox>
</lightning-layout-item>

JS:

import { LightningElement, wire, track } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import ACCOUNT_OBJECT from '@salesforce/schema/Account';
import TYPE_FIELD from '@salesforce/schema/Account.Type';
import getAccounts from '@salesforce/apex/MyClass.getAccounts';

export default class TestLwcPicklist extends LightningElement {
 
@track typeValues;
@track isTypeSelected = true;
@track accountNamePicklist = [];
@track typeSelected;
@wire(getObjectInfo, { objectApiName: ACCOUNT_OBJECT })
    objectInfo;

    @wire(getPicklistValues, { recordTypeId: '$objectInfo.data.defaultRecordTypeId', fieldApiName: TYPE_FIELD })
    typePicklistValues({ data, error }) {
        if (data) {
            this.typeValues = data.values;
            this.error = undefined;
        }
        if (error) {
            this.error = error;
            this.typeValues = undefined;
        }
    }
handleProductChange(event) {
            this.typeSelected = event.detail.value;
            this.isTypeSelected = false;
            
            this.fetchAccountNamePicklist();
        }
    
        fetchAccountNamePicklist() {
            getAccounts({ type: this.typeSelected })
                .then(result => {
                    this.account = result;
                    this.error = undefined;
                    this.account.forEach(row => {
                        let name = { label:row.Name, value:row.Name };
                        this.accountNamePicklist.push(name);
                    })
                })
                .catch(error => {
                    this.error = error;
                    this.account = undefined;
                })
                
            
    
        }
    
    get accountNames() {
            return this.accountNamePicklist;
        }
}

APEX:

@AuraEnabled
public static List<Account> getAccounts(String type){
     List<Account> lstAcc = [SELECT Id, Name, Type from Account Where Type = :type]
     return lstAcc
}

One Answer

The property account will be undefined first time, because you have misplaced the for-loop in the below code.

fetchAccountNamePicklist() {
        getAccounts({ type: this.typeSelected })
            .then(result => {
                this.account = result;
                this.error = undefined;
            })
            .catch(error => {
                this.error = error;
                this.account = undefined;
            })

            for (var i = 0; i < this.account.length; i++) {
                this.accountNamePicklist = [...this.accountNamePicklist, { label: this.account[i].Name, value: this.account[i].Name }];
            }
    }

Which should be like this.

fetchAccountNamePicklist() {
    getAccounts({ type: this.typeSelected })
        .then(result => {
            this.account = result;
            for (let i = 0; i < this.account.length; i++) {
                this.accountNamePicklist = [...this.accountNamePicklist, { label: this.account[i].Name, value: this.account[i].Name }];
            }
            this.error = undefined;
        })
        .catch(error => {
            this.error = error;
            this.account = undefined;
        })
    }
}

Also note that as you have not used the account property anywhere else, you don't even need to store it. You can simply generate the options right there based on the result.

Also a few other improvements you can do.

  • Always use let instead of var for block-scoped variables.
  • the for-loop you have used to set accountNamePicklist is not efficient. instead of that use the array.map(). Its a bad idea to clone the array, inside the for-loop. you could have used array.push() as well.

Correct answer by rahul gawale on September 30, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP