2

We have built a Lightning Component for displaying OrderLines__c (custom object). Since we need to utilize picklist values we could not use the lightning:datatable. I found a great guide on sfdcmonkey.com (http://sfdcmonkey.com/2017/12/08/lightning-data-table-inline-editing/) of how to build my own data table with inline edit supporting picklists.

The problem is that our OrderLines__c object is also utilizing Record Types. However there does not seem to be a straight forward way to get the picklist values for a specific Record Type in Apex. I can use the User Interface API (https://developer.salesforce.com/docs/atlas.en-us.uiapi.meta/uiapi/ui_api_resources_picklist_values.htm).

But since every OrderLine__c is its own component. This mean there is going to be one call for every line. Which is going to end up in a lot of API calls.

So my question is: What is the best approach to handle this?

I have been thinking about using Apex Scheduler and update a static resource with the current values. However I am hoping there is a better solution.

  • Why don't you still use lightning:dataTable and have a client side validation to verify if your picklist input maps to one of the picklist values applicable for that record type? And you can instruct Users to enter only specific values as applicable for that field. This way you won't have to make any server trips at all, and still be able to achieve your goal. – Jayant Das Oct 31 '18 at 16:33
  • It is not viable to have the users remembering all the values that valid for each record type. – user3274635 Nov 1 '18 at 10:23
  • Agreed. But to reduce complexity, there are couple of other ways to let Users know which is applicable where. E.g., you can have a sort of "help" ink right on your component to display all applicable values. And that you can construct those values when your component initializes. That way you don't have to make server trips. – Jayant Das Nov 1 '18 at 12:29
1

You can use a helper object to share data across multiple components. This is the principle behind the lightning:empApi component; it shares a connection across multiple components to multiplex a streaming API connection. I'm not going to write a full, production-ready solution for this, but I have written a demo that should get you started.


<aura:component controller="DescribeRequestController">
    <aura:handler name="init" action="{!c.init}" value="{!this}" />
    <aura:method name="getDescribe" action="{!c.handleDescribeRequest}">
        <aura:attribute name="entityName" type="String" />
        <aura:attribute name="callback" type="Function" />
    </aura:method>
</aura:component>

({
    init: function(component, event, helper) {
        helper.init();
    },
    handleDescribeRequest: function(component, event, helper) {
        helper.handleDescribe(component, event);
    }
})

({
    init: function() {
        // state information
        this.queue = [];
        this.describes = {};
        this.isInCallback = false;
    },
    handleDescribe: function(component, event) {
        var params = event.getParams();
        if(this.describes[params.entityName]) {
            // We already described this!
            params.callback(this.describes[params.entityName]);
        } else {
            // Place into queue for processing
            this.queue.push(params);
            this.handleDescribeCallback(component, event);
        }
    },
    handleDescribeCallback: function(component, event) {
        // We're waiting on other results
        if(this.isInCallback) {
            return;
        }
        this.isInCallback = true;
        var action = component.get("c.getDescribe");
        action.setParams({entityName: this.queue[0].entityName });
        action.setCallback(this, function(result) {
            // We're not busy after this
            this.isInCallback = false;
            this.describes[this.queue[0].entityName] = JSON.parse(result.getReturnValue());
            // Find all pending items that were waiting for this describe, do callback
            this.queue.filter(item => this.describes[item.entityName])
                .forEach(item => item.callback(this.describes[item.entityName]));
            // Remove all those items we just dispatched
            this.queue = this.queue.filter(item => !this.describes[item.entityName]);
            // If we have any more work to do, let's do so
            if(this.queue.length) {
                this.handleDescribeCallback(component, event);
            }
        });
    }
})

public class DescribeRequestController {
  @AuraEnabled public static String getDescribe(String entityName) {
    HttpRequest req = new HttpRequest();
    req.setMethod('GET');
    req.setEndpoint(
      'callout:salesforce/services/data/v43.0/sobjects/'+
      entityName+'/describe');
    return new http().send(req).getBody();
  }
}

This code, of course, doesn't have any error handling, and should not be considered production-ready, but it should demonstrate enough technique to get you to a viable solution. Once you have the describe info, you'll have the "validFor" bitmap, which you'll need to parse yourself. See this answer for how to parse this bitmap.

  • Thanks for your reply. Not sure if I am doing this correctly. I created a child component similar to your example. I am calling this from my component that displays OrderLines__c. If I have 25 OrderLines__c, there is still 25 API calls made. Also, my topic might be a bit miss leading. I am looking to get which picklist values that are valid for a Record Type. As far as I understand, the data you get from describe is values that are dependent on other values. – user3274635 Nov 1 '18 at 10:22
  • @user3274635 Sorry, that was partly my fault. I meant to say that you should be able to examine the recordTypeInfos returned from this call. As far as the API call being made 25 times, it's possible there's some logic bugs with my code; it was only meant to be illustrative, not literal. I'll see if I can do some debugging on this, but it might take me a while. – sfdcfox Nov 1 '18 at 12:30
0

You can try using lightning/uiApi of LWC components and get respective picklist values Refer this git link for example

For getting specific field picklist vlaue base on record type id you can use uiObjectInfoApi and that will return your data to lighting component and

LWC COMPONENT JS(getpicklist)

import { LightningElement, wire } from 'lwc';
import { getPicklistValues } from 'lightning/uiObjectInfoApi';
import customFiled from '@salesforce/schema/OrderLines__c.customFiled__c';

export default class Example extends LightningElement {
@api recordtypeId;
@wire(getPicklistValues, { recordTypeId: '$recordtypeId', fieldApiName: 
      customFiled })
     gettingPicklistValue({error,data}){
        if(data){
            //on retriving data creating a custom event to send data
            const layoutDataEvent = new CustomEvent('picklistDataRecive', {
                 detail: { picklistData:data },
              });
            this.dispatchEvent(layoutDataEvent);
         }
     }
}

AURA COMPONENT

<aura:attribute name="pickListDetails" type="Object[]"/>
<!--LWC component returning obj details-->
<getpicklist recordtypeId="012000000000000AAA" onpicklistDataRecive=" 
{!c.handlePicklistDetails}"> 
</getpicklist>

Aura Component Controler

({
handlePicklistDetails : function(component, event, helper) {
    //getting object data from event 
    let data=event.getParam('picklistData');
    console.log(JSON.parse(JSON.stringify(data)));
    component.set('v.pickListDetails',data)

}
})

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.