Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Picklist Values By Record Type

Salesforce has never had a built-in Apex way to fetch a field's picklist values filtered to a specific Record Type — Schema.DescribeFieldResult.getPicklistValues() only returns the field's global active values, ignoring any per-record-type restrictions configured in Setup. This package closes that gap with two small, generic Apex classes, with no dependency on any specific object, field, or org.

What's included

Class Purpose
PicklistValuesByRecordType Bulk-safe @InvocableMethod — callable from Flow, Process Builder, or directly via the REST Invocable Actions API.
PicklistValuesByRecordTypeCallable A Callable-interface adapter for invoking the same logic from OmniStudio Integration Procedure / OmniScript "Remote Action" elements.

Both classes use ConnectApi.RecordUi.getPicklistValuesByRecordType internally (a native Apex method available from Spring '26 onward) — no callouts, no manual metadata parsing, and it correctly respects controlling-field/dependent-picklist restrictions for the given record type.

Requirements

  • API version 66.0+ (Spring '26 or later) — required for ConnectApi.RecordUi.getPicklistValuesByRecordType.
  • Apex Class Access for both classes must be granted via a permission set to any user/profile that needs to invoke them (not required for system-context Flow execution).

Usage: PicklistValuesByRecordType (Flow / REST)

From Flow

Add an Action element, search for "Get Picklist Values By Record Type", and supply:

  • Record Type Id — the Id of the record type to filter by.
  • Field API Name — the picklist field's API name (e.g. Industry, MyCustomField__c).

The action is bulk-safe: in a loop, each iteration is processed independently, and one invalid row doesn't fail the rest of the batch. The response includes:

  • Is Success (Boolean)
  • Error Message (String, populated only when Is Success is false)
  • Picklist Values (List of {label, value})

From REST

POST /services/data/v60.0/actions/custom/apex/PicklistValuesByRecordType
Content-Type: application/json
Authorization: Bearer <session token>

{
  "inputs": [
    { "recordTypeId": "012000000000000AAA", "fieldApiName": "Industry" }
  ]
}

Response:

[
  {
    "actionName": "PicklistValuesByRecordType",
    "isSuccess": true,
    "outputValues": {
      "isSuccess": true,
      "errorMessage": null,
      "picklistValues": [
        { "label": "Agriculture", "value": "Agriculture" },
        { "label": "Banking", "value": "Banking" }
      ]
    }
  }
]

Usage: PicklistValuesByRecordTypeCallable (OmniStudio)

OmniStudio's Remote Action elements need an Apex class implementing the standard Callable interface, not a plain @InvocableMethod. Rather than wiring up structured "Additional Input"/Set Values mappings (which proved unreliable across different OmniStudio Designer versions in practice), this class takes a single composite string and resolves everything from it.

Configuring the Remote Action element

Property Value
Remote Class PicklistValuesByRecordTypeCallable
Remote Method SObjectType::RecordTypeDeveloperName::FieldApiName

For example, to get the values of a custom picklist field MyCustomField__c on MyObject__c, restricted to the record type with developer name MyRecordType:

Remote Method: MyObject__c::MyRecordType::MyCustomField__c

The double-colon (::) delimiter is deliberate — Salesforce API names and Record Type developer names can contain underscores, so a single underscore would be ambiguous as a separator. Colons never appear in either, so splitting is always unambiguous.

Output

The result is written into the Remote Action's output (surfaced under its Remote key in the Integration Procedure / OmniScript context):

{
  "isSuccess": true,
  "errorMessage": null,
  "options": [
    { "name": "Agriculture", "value": "Agriculture" },
    { "name": "Banking", "value": "Banking" }
  ]
}

Note on name/value orientation: some OmniStudio Select element configurations expect name to hold the underlying value and value to hold the display label — the reverse of what the key names suggest. This was confirmed empirically against a specific org's OmniStudio Select element and is encoded in PicklistValuesByRecordTypeCallable's serialize() method. If your org's Select elements expect the conventional orientation instead (name = display label, value = underlying value), swap the two arguments in that method.

Running the tests

Both test classes use @IsTest(SeeAllData=true). This is not optional and is not a sign of fragile test design: any Apex test exercising ConnectApi.* methods is required by the platform to use SeeAllData=true, regardless of what data the code actually touches. The tests here only ever read RecordType metadata (Setup configuration) and standard Account picklist fields (Industry) — never transactional business records — so this requirement doesn't introduce the usual risks associated with SeeAllData=true (fragile dependence on org data state).

sf project deploy start --source-dir force-app --test-level RunLocalTests

Installing

This is structured as an unlocked package. To create and install a version:

sf package version create --package "Picklist Values By Record Type" --installation-key-bypass --wait 20
sf package install --package <package-version-id> --target-org <your-org> --wait 10

Alternatively, deploy the source directly without packaging:

sf project deploy start --source-dir force-app --target-org <your-org>

After installing, grant Apex Class Access for both classes via a permission set to any non-admin user/profile that needs to invoke them directly (e.g. from a Screen Flow running in user context, or a Community/Experience Cloud user).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages