Implement a Data Provider

A data provider is a reference to a source of data. It’s implemented as a function within an Apex class.

To pull data into a view, bind the view to a data provider. To reference the data throughout a view, use an expression.

Apex Data Types 

You can use these data types for input and output in Apex methods.

Data TypeDescriptionExamples
PrimitiveBoolean, Date, DateTime, Decimal, Double, Integer, Long, and String- Primitive Input and Primitive Output
- Primitive Input and List<Primitive> Output
sObjectA row of data declared using the SOAP API name of the object. Both standard and custom objects are supported.- Standard Object Input and List Output
- Custom Object Output
- List<sObject> Output
- Map with Contact List Output
ApexAn instance of an Apex classApex Class Output
CollectionA list, set, or map- Standard Object Input and List Output
-List<sObject> Output
- Primitive Input and List<Primitive> Output
- Map with Contact List Output

Bind Apex Methods to Components 

To bind a data provider to a component, follow this syntax for the definition value.

1apex__[ApexNamespace].ApexClassName.ApexMethod

For example:

1dataproviders:
2  yourData:
3    definition: "apex__MyDataProvider.getYourDataFromApexClass"

The arguments passed to the Apex method are specified as properties to the data provider. The property key must match the name of the parameter in the Apex method signature.

Data Providers for Select and External Select Components 

The Select component uses the dataproviders property to bind a data provider to the view.

To create a data provider for a Select component, construct a List<Slack.Option> or List<Slack.OptionGroup> for your view definition.

The External Select component uses the datasource property to bind a data provider to the view. For the External Select component, your Apex methods must follow certain method signature restrictions.

  • Must have a String value as the first parameter in addition to any other parameters already present.
  • Must return Slack.OptionDataResponse. Construct Slack.OptionDataResponse with List<Slack.OptionGroup> or List<Slack.Option>. All items in the same Slack.OptionDataResponse must be of the same type.

Constructing a Slack.OptionDataResponse with a combination of Slack.Option and Slack.OptionGroup isn’t supported.

Important

The optional value parameter provides the input string entered into the select component that’s used to perform the lookup. The value you provide preselects an option from the options identifier or from your data provider.

1components:
2  - definition: select
3    properties:
4      name: "StageName"
5      value: "Prospecting"
6      placeholder: "Select a stage."
7      options:
8        - identifier: "Prospecting"
9          label: "Prospecting"
10        - identifier: "Qualification"
11          label: "Qualification"

See more examples.

Examples 

These examples show you how to create a data provider with Apex data types.

Primitive Input and Primitive Output 

Apex method:

1public class EchoExample {
2    public static String echo(String echoStr) {
3        return echoStr;
4    }
5}

View:

1description: "This simple view contains an Apex echo data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "Echo ApexDataProvider"
7    myString:
8      type: string
9      default: "Hello, World!"
10dataproviders:
11  echoStr:
12    definition: "apex__EchoExample.echo"
13    properties:
14      echoStr: "{!view.properties.myString}"
15components:
16  - definition: modal
17    properties:
18      title: "{!view.properties.title}"
19    components:
20      - definition: section
21        properties:
22          text: "{!echoStr}" # will render Hello, World!

Standard Object Input and List Output 

Apex method:

1public class ObjectInputListOutputExample {
2    public static List<Contact> getAccountContacts(Account acct) {
3        List<Contact> contacts = [
4            SELECT Id, Name, Title, Phone, Email
5            FROM Contact
6            WHERE AccountId = :acct.Id
7            WITH SECURITY_ENFORCED
8            LIMIT 10
9        ];
10
11        return contacts;
12    }
13}

View:

1description: "This list view contains an Apex Contact list data provider for an Account"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "Account Contacts ApexDataProvider"
7    accountId:
8      type: string
9      defaultValue: "001xx000003GYQRAA4"
10dataproviders:
11  contacts:
12    definition: "apex__ObjectInputListOutputExample.getAccountContacts"
13    properties:
14      acct:
15        Id: "{!view.properties.accountId}"
16components:
17  - definition: modal
18    properties:
19      title: "{!view.properties.title}"
20    components:
21      - definition: header
22        properties:
23          text: "My Contacts"
24      - definition: iteration
25        properties:
26          foreach: "{!contacts}"
27          foritem: "contact"
28        components:
29          - definition: divider
30          - definition: section
31            properties:
32              text: "{!contact.Name}"
33          - definition: section
34            properties:
35              text:
36                text: "*Id:* {!contact.Id}"
37                type: mrkdwn
38          - definition: section
39            properties:
40              text:
41                text: "*Title:* {!contact.Title}"
42                type: mrkdwn
43          - definition: section
44            properties:
45              text:
46                text: "*Phone:* {!contact.Phone}"
47                type: mrkdwn
48          - definition: section
49            properties:
50              text:
51                text: "*Email:* {!contact.Email}"
52                type: mrkdwn

Apex Class Output 

Apex method:

1public class ClassOutputExample {
2    public static TestClass getApexClass() {
3        return new TestClass();
4    }
5}
6
7// User-defined Apex class
8public class TestClass {
9    public final String myString = 'Hello from TestClass class!';
10}

View:

1description: "This simple view contains an Apex user type data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "UserType ApexDataProvider"
7dataproviders:
8  apexClass:
9    definition: "apex__ClassOutputExample.getApexClass"
10components:
11  - definition: modal
12    properties:
13      title: "{!view.properties.title}"
14    components:
15      - definition: section
16        properties:
17          text: "{!apexClass.myString}"

Custom Object Output 

Apex method:

1public class CutomObjectOutputExample {
2    public static MyCustomObject__c getCustomObject(Id objectId) {
3        MyCustomObject__c customObject = [
4            SELECT Id, Name, CustomTextField__c, CustomDateField__c, CustomNumberField__c
5            FROM MyCustomObject__c
6            WHERE Id = :objectId
7            WITH SECURITY_ENFORCED
8        ];
9
10        return customObject;
11    }
12}

View:

1description: "This simple view contains an Apex single custom object data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "CustomObject ApexDataProvider"
7    objectId:
8      type: string
9      defaultValue: "a00xx000000boMTAAY"
10dataproviders:
11  customobject:
12    definition: "apex__CutomObjectOutputExample.getCustomObject"
13    properties:
14      objectId: "{!view.properties.objectId}"
15components:
16  - definition: modal
17    properties:
18      title: "{!view.properties.title}"
19    components:
20      - definition: header
21        properties:
22          text: "CustomObject: {!view.properties.objectId}"
23      - definition: section
24        properties:
25          text: "{!customobject.Name}"
26      - definition: section
27        properties:
28          text:
29            text: "*Id:* {!customobject.Id}"
30            type: mrkdwn
31      - definition: section
32        properties:
33          text:
34            text: "*Custom Text Field:* {!customobject.CustomTextField__c}"
35            type: mrkdwn
36      - definition: section
37        properties:
38          text:
39            text: "*Custom Date Field:* {!customobject.CustomDateField__c}"
40            type: mrkdwn
41      - definition: section
42        properties:
43          text:
44            text: "*Custom Number Field:* {!customobject.CustomNumberField__c}"
45            type: mrkdwn

sObject List Output 

Apex method:

1public class ListOutputExample {
2    public static List<Contact> getContactList() {
3        List<Contact> contacts = [
4            SELECT Id, Name, Title, Phone, Email
5            FROM Contact
6            WITH SECURITY_ENFORCED
7            LIMIT 10
8        ];
9
10        return contacts;
11    }
12}

View:

1description: "This is a simple list view containing an Apex contact list data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "Contacts ApexDataProvider"
7dataproviders:
8  contacts:
9    definition: "apex__ListOutputExample.getContactList"
10components:
11  - definition: modal
12    properties:
13      title: "{!view.properties.title}"
14    components:
15      - definition: header
16        properties:
17          text: "My Contacts"
18      - definition: iteration
19        properties:
20          foreach: "{!contacts}"
21          foritem: "contact"
22        components:
23          - definition: divider
24          - definition: section
25            properties:
26              text: "{!contact.Name}"
27          - definition: section
28            properties:
29              text:
30                text: "*Id:* {!contact.Id}"
31                type: mrkdwn
32          - definition: section
33            properties:
34              text:
35                text: "*Title:* {!contact.Title}"
36                type: mrkdwn
37          - definition: section
38            properties:
39              text:
40                text: "*Phone:* {!contact.Phone}"
41                type: mrkdwn
42          - definition: section
43            properties:
44              text:
45                text: "*Email:* {!contact.Email}"
46                type: mrkdwn

Primitive Input and Primitive List Output 

Apex method:

1public class StringListExample {
2    public static String[] echoMultiple(String string1, String string2, String string3) {
3        List<String> myList = new List<String>();
4        myList.add(string1);
5        myList.add(string2);
6        myList.add(string3);
7        return myList;
8    }
9}

View:

1description: "This is a simple list view containing an Apex echo list data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "EchoMultiple ApexDataProvider"
7    string1:
8      type: string
9      required: true
10    string2:
11      type: string
12      required: true
13    string3:
14      type: string
15      required: true
16dataproviders:
17  echoStrings:
18    definition: "apex__StringListExample.echoMultiple"
19    properties:
20      string1: "{!view.properties.string1}"
21      string2: "{!view.properties.string2}"
22      string3: "{!view.properties.string3}"
23components:
24  - definition: modal
25    properties:
26      title: "{!view.properties.title}"
27    components:
28      - definition: iteration # iterate through list of strings
29        properties:
30          foreach: "{!echoStrings}"
31          foritem: "echoStr"
32        components:
33          - definition: section
34            properties:
35              text: "{!echoStr}"

Map with Contact List Output 

Apex method:

1public class MapContactListExample {
2    publicstatic Map<Id, List<Contact>> getAccountContactMap() {
3        List<Contact> contacts = [
4            SELECT Id, Name, Title, Phone, Email, AccountId
5            FROM Contact
6            WITH SECURITY_ENFORCED
7            LIMIT 10
8        ];
9        Map<Id, List<Contact>> contactMap = new Map<Id, List<Contact>>();
10        for (Contact contact : contacts) {
11            Id acctId = contact.AccountId;
12            if (!contactMap.containsKey(acctId)) {
13                contactMap.put(acctId, new List<Contact>());
14            }
15            contactMap.get(acctId).add(contact);
16        }
17
18        return contactMap;
19    }
20}

View:

1description: "This is a simple list view containing an Apex account contact map data provider"
2schema:
3  properties:
4    title:
5      type: string
6      defaultValue: "Account Contacts ApexDataProvider"
7dataproviders:
8  contacts:
9    definition: "apex__MapContactListExample.getAccountContactMap"
10components:
11  - definition: modal
12    properties:
13      title: "{!view.properties.title}"
14    components:
15      - definition: header
16        properties:
17          text: "My Contacts for 001xx000003GYQRAA4"
18      - definition: iteration
19        properties:
20          foreach: "{!contacts.001xx000003GYQRAA4}"
21          foritem: "contact"
22        components:
23          - definition: divider
24          - definition: section
25            properties:
26              text: "{!contact.Name}"
27          - definition: section
28            properties:
29              text:
30                text: "*Id:* {!contact.Id}"
31                type: mrkdwn
32          - definition: section
33            properties:
34              text:
35                text: "*Title:* {!contact.Title}"
36                type: mrkdwn
37          - definition: section
38            properties:
39              text:
40                text: "*Phone:* {!contact.Phone}"
41                type: mrkdwn
42          - definition: section
43            properties:
44              text:
45                text: "*Email:* {!contact.Email}"
46                type: mrkdwn

This example is from view_contact.view in the sample app.

Tip

External Select 

Apex data provider using List<Slack.Option> and returning Slack.OptionDataResponse:

1global class AccountDataProvider {
2 global static Slack.OptionDataResponse getAccountsByName(String value) {
3    String name = '%'+ value + '%';
4    List<Account> accounts = [
5      SELECT Id, Name
6      FROM Account
7      WHERE Name LIKE :name
8      WITH SECURITY_ENFORCED
9      LIMIT 10
10    ];
11     System.debug('retrieved accounts');
12     List<Slack.Option> accountOptions = new List<Slack.Option>();
13     for(Account account: accounts) {
14         Slack.Option option = new Slack.Option(account.Name, account.Id);
15         System.debug(option.getText());
16         accountOptions.add(option);
17     }
18    return new Slack.OptionDataResponse(accountOptions);
19  }
20}

Apex data provider using List<Slack.OptionGroup> and returning Slack.OptionDataResponse:

1global class ContactDataProvider {
2 global static Slack.OptionDataResponse getContactGroupsByName(String value) {
3    String name = '%'+ value + '%';
4    List<Contact> contacts = [
5      SELECT Name, Id, AccountId, Account.name
6      FROM Contact
7      WHERE Name LIKE :name
8      LIMIT 10
9    ];
10     Map<Id, List<Slack.Option>> contactsByAccount = new Map<Id, List<Slack.Option>>();
11     Map<Id, String> accountNames = new Map<Id,String>();
12     for(Contact contact: contacts) {
13         List<Slack.Option> options = contactsByAccount.get(contact.AccountId);
14         Slack.Option currentOption = new Slack.Option(contact.name, contact.id);
15         if (options == null) {
16            List<Slack.Option> newList = new List<Slack.Option>();
17            newList.add(currentOption);
18            contactsByAccount.put(contact.AccountId, newList);
19            accountNames.put(contact.AccountId, contact.Account.name);
20         } else {
21             options.add(currentOption);
22        }
23     }
24     List<Slack.OptionGroup> contactOptionGroups = new List<Slack.OptionGroup>();
25     for(Id key : contactsByAccount.keySet()) {
26         String accountName = accountNames.get(key);
27         System.debug(key);
28         Slack.OptionGroup optionGroup = new Slack.OptionGroup(accountName, contactsByAccount.get(key));
29         System.debug(optionGroup.getLabel());
30         contactOptionGroups.add(optionGroup);
31     }
32    return new Slack.OptionDataResponse(contactOptionGroups);
33  }
34}

View:

1description: "View with external select examples."
2components:
3  - definition: modal
4    properties:
5      title: "External Select"
6    components:
7      - definition: section
8        properties:
9          text: "Select an Account"
10      - definition: actions
11        name: "external_select_accounts"
12        components:
13          - definition: externalSelect
14            properties:
15              placeholder: "Look up an account by name"
16              name: "account_lookup"
17              datasource:
18                definition: "apex__AccountDataProvider.getAccountsByName"
19      - definition: section
20        properties:
21          text: "Select a Contact"
22      - definition: actions
23        name: "external_select_contacts"
24        components:
25          - definition: externalSelect
26            properties:
27              placeholder: "Look up a Contact by name"
28              name: "contact_lookup"
29              datasource:
30                definition: "apex__ContactDataProvider.getContactGroupsByName"

This example is from create_opportunity.view in the sample app.

Tip

Beta Feature

This feature is not generally available. It is not part of your purchased Services. This feature is subject to change, may be discontinued with no notice at any time in SFDC’s sole discretion, and SFDC may never make this feature generally available. Make your purchase decisions only on the basis of generally available products and features. This feature is made available on an AS IS basis and use of this feature is at your sole risk.