2

I want to provide users with options in a LWC select that are the values in a records field. For example, if a custom object has a field of Category. The Category field has several options that are used on records - Active, Ended, Completed, etc. I want to display those options. I don't want to just pull in the values of a picklist. I want to show only the options that are being used on records.

I don't believe this question is the same as what I have seen in Stack Exchange. I don't want to retrieve the picklist values of an object's field. Instead, I want to display a unique list of values that appear in a field. This field could be a picklist field or not a picklist field.

This is what I have right now:

                    <select class="slds-select partial-width" name="TypeSelect" data-id="TypeSelect" onchange={handleChange} >
                    <option value="">All</option>
                    <option value="Workforce">Workforce</option>
                    <option value="Technical">Technical</option>
                </select> 
2
  • Categories being a picklist field? Nov 15, 2019 at 16:30
  • Correct - I updated my question with the code I am currently using with hardcoded values. I want to move away from that. Nov 15, 2019 at 17:01

2 Answers 2

1

You can either use lightning-combobox and filter values coming from your apex controller (maybe based on a record type for the records?) or use another base component with hardcoded values like pill component.

3
  • Pls check out the code I added to the question that I am currently using. Are you saying I need to switch to lightning-combobox instead of select? Nov 15, 2019 at 17:00
  • As far as I know there isn't a component called select for web components. If you want to dynamically filter values on records you would need to do it in your apex controller.
    – Atlas Can
    Nov 15, 2019 at 17:03
  • I can get the data I want to display in my Apex controller. I don't know how to give that to the LWC select so that it will be used for the picklist values. Nov 15, 2019 at 17:07
0

I did this in a component I made that is available on github.

Basically, I use an apex controller to perform an aggregate query on the contact object grouped by the fields I wanted (State and city). Then, I loop through the values returned to my js controller and create an array of states and a map of Lists of cities with the states as the key. Then, when the value of the picklist changes on the page, the state is selected in the controller and the available cities is updated to the cities for the given state creating what is effectively a dependent picklist.

I would add a disclaimer that I'm not a JS guru so there is probably a cleaner way to do it but it does work.

Here is the important bits of the code, I trimmed out parts that shouldn't matter

HTML:

<lightning-layout-item class="slds-p-horizontal_x-small" size="6">
    <lightning-combobox
        name="State"
        label="State"
        value={selectedState}
        options={states}
        onchange={handleStateChange}
    ></lightning-combobox>
</lightning-layout-item>
<lightning-layout-item class="slds-p-horizontal_x-small" size="6">
    <lightning-combobox
        name="City"
        label="City"
        value={selectedCity}
        options={cities}
        onchange={handleCityChange}
    ></lightning-combobox>
</lightning-layout-item>

JS:

import getStateMap from '@salesforce/apex/ContractorSearchController.getStateMap';

@wire(getRecord, {recordId:'$recordId', fields:requisitionFields})
getRequisition({error, data}) { 
    this.contractors = undefined;
    this.selectedContractors = undefined;

    // Call the apex method
    /* I call the apex method in this location as I wanted to chain the responses
       Later on in the code I use the record to set default values on the picklists
       In order for this to work in an async fasion, I need to control the execution
       order and timing.*/
    getStateMap().then(
        result => {
            let keys = Reflect.ownKeys(result);
            let s = [];
            this.stateMap = [];

            keys.forEach(function(stateName) {
                let c = [];

                result[stateName].forEach(function(cityName) {
                    c.push({label: cityName, value:cityName});
                }, this);

                s.push({label:stateName, value:stateName});
                this.stateMap[stateName] = c;
            }, this);

            this.states = s;

            /* Code Removed, basically it just uses the record to set default
               values for the various field sin my component */

        }
    ).catch(
        result => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error creating assignment',
                    message: result.body.message,
                    variant: 'error',
                }),
            );
        }
    );
}

handleStateChange(event) {
    this.selectedState = event.detail.value;
    this.cities = this.stateMap[this.selectedState];
    this.selectedCity = this.cities[0].value;
}

handleCityChange(event) {
    this.selectedCity = event.detail.value;
}

Apex:

@AuraEnabled(cacheable=true)
public static Map<String, Object> getStateMap(){
    system.debug(contractorRecordTypeId);
    Map<String, Set<String>> stateToCity = new Map<String, Set<String>>();

    for (AggregateResult ar : [
        SELECT MailingState, MailingCity
        FROM Contact
        WHERE MailingState != null
            AND MailingCity != null
            AND RecordTypeId = :contractorRecordTypeId
        GROUP BY MailingState, MailingCity
        ORDER BY MailingState ASC, MailingCity ASC
    ]) {
        system.debug(string.valueOf(ar));
        String mailingState = (String) ar.get('MailingState');
        String mailingCity = (String) ar.get('MailingCity');

        if (!stateToCity.containsKey(mailingState)) {
            stateToCity.put(mailingState, new Set<String>());
        }

        stateToCity.get(mailingState).add(mailingCity);
    }

    return stateToCity;
}

Update

As for using the native HTML select tag, I am unsure of whether or not that will work. I have not tried to attach events to native tags or tested what the event information has. I would expect you will end up doing some DOM traversing which is gross.

If you absolutely need to go that route, you could use <template for:each={data} for:item="value"> ...</template> in your html code to loop through the array and create select options.

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