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 Type | Description | Examples |
|---|---|---|
| Primitive | Boolean, Date, DateTime, Decimal, Double, Integer, Long, and String | - Primitive Input and Primitive Output<br> - Primitive Input and List<Primitive> Output |
| sObject | A 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<br> - Custom Object Output<br> - List<sObject> Output<br> - Map with Contact List Output |
| Apex | An instance of an Apex class | Apex Class Output |
| Collection | A list, set, or map | - Standard Object Input and List Output<br> -List<sObject> Output<br> - Primitive Input and List<Primitive> Output<br> - 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.
apex__[ApexNamespace].ApexClassName.ApexMethod
For example:
dataproviders:
yourData:
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. ConstructSlack.OptionDataResponsewithList<Slack.OptionGroup>orList<Slack.Option>. All items in the sameSlack.OptionDataResponsemust be of the same type.
important: Constructing a Slack.OptionDataResponse with a combination of Slack.Option and Slack.OptionGroup isn’t supported.
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.
components:
- definition: select
properties:
name: "StageName"
value: "Prospecting"
placeholder: "Select a stage."
options:
- identifier: "Prospecting"
label: "Prospecting"
- identifier: "Qualification"
label: "Qualification"
Examples
These examples show you how to create a data provider with Apex data types.
Primitive Input and Primitive Output
Apex method:
public class EchoExample {
public static String echo(String echoStr) {
return echoStr;
}
}
View:
description: "This simple view contains an Apex echo data provider"
schema:
properties:
title:
type: string
defaultValue: "Echo ApexDataProvider"
myString:
type: string
default: "Hello, World!"
dataproviders:
echoStr:
definition: "apex__EchoExample.echo"
properties:
echoStr: "{!view.properties.myString}"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: section
properties:
text: "{!echoStr}" # will render Hello, World!
Standard Object Input and List Output
Apex method:
public class ObjectInputListOutputExample {
public static List<Contact> getAccountContacts(Account acct) {
List<Contact> contacts = [
SELECT Id, Name, Title, Phone, Email
FROM Contact
WHERE AccountId = :acct.Id
WITH SECURITY_ENFORCED
LIMIT 10
];
return contacts;
}
}
View:
description: "This list view contains an Apex Contact list data provider for an Account"
schema:
properties:
title:
type: string
defaultValue: "Account Contacts ApexDataProvider"
accountId:
type: string
defaultValue: "001xx000003GYQRAA4"
dataproviders:
contacts:
definition: "apex__ObjectInputListOutputExample.getAccountContacts"
properties:
acct:
Id: "{!view.properties.accountId}"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: header
properties:
text: "My Contacts"
- definition: iteration
properties:
foreach: "{!contacts}"
foritem: "contact"
components:
- definition: divider
- definition: section
properties:
text: "{!contact.Name}"
- definition: section
properties:
text:
text: "*Id:* {!contact.Id}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Title:* {!contact.Title}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Phone:* {!contact.Phone}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Email:* {!contact.Email}"
type: mrkdwn
Apex Class Output
Apex method:
public class ClassOutputExample {
public static TestClass getApexClass() {
return new TestClass();
}
}
// User-defined Apex class
public class TestClass {
public final String myString = 'Hello from TestClass class!';
}
View:
description: "This simple view contains an Apex user type data provider"
schema:
properties:
title:
type: string
defaultValue: "UserType ApexDataProvider"
dataproviders:
apexClass:
definition: "apex__ClassOutputExample.getApexClass"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: section
properties:
text: "{!apexClass.myString}"
Custom Object Output
Apex method:
public class CutomObjectOutputExample {
public static MyCustomObject__c getCustomObject(Id objectId) {
MyCustomObject__c customObject = [
SELECT Id, Name, CustomTextField__c, CustomDateField__c, CustomNumberField__c
FROM MyCustomObject__c
WHERE Id = :objectId
WITH SECURITY_ENFORCED
];
return customObject;
}
}
View:
description: "This simple view contains an Apex single custom object data provider"
schema:
properties:
title:
type: string
defaultValue: "CustomObject ApexDataProvider"
objectId:
type: string
defaultValue: "a00xx000000boMTAAY"
dataproviders:
customobject:
definition: "apex__CutomObjectOutputExample.getCustomObject"
properties:
objectId: "{!view.properties.objectId}"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: header
properties:
text: "CustomObject: {!view.properties.objectId}"
- definition: section
properties:
text: "{!customobject.Name}"
- definition: section
properties:
text:
text: "*Id:* {!customobject.Id}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Custom Text Field:* {!customobject.CustomTextField__c}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Custom Date Field:* {!customobject.CustomDateField__c}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Custom Number Field:* {!customobject.CustomNumberField__c}"
type: mrkdwn
sObject List Output
Apex method:
public class ListOutputExample {
public static List<Contact> getContactList() {
List<Contact> contacts = [
SELECT Id, Name, Title, Phone, Email
FROM Contact
WITH SECURITY_ENFORCED
LIMIT 10
];
return contacts;
}
}
View:
description: "This is a simple list view containing an Apex contact list data provider"
schema:
properties:
title:
type: string
defaultValue: "Contacts ApexDataProvider"
dataproviders:
contacts:
definition: "apex__ListOutputExample.getContactList"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: header
properties:
text: "My Contacts"
- definition: iteration
properties:
foreach: "{!contacts}"
foritem: "contact"
components:
- definition: divider
- definition: section
properties:
text: "{!contact.Name}"
- definition: section
properties:
text:
text: "*Id:* {!contact.Id}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Title:* {!contact.Title}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Phone:* {!contact.Phone}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Email:* {!contact.Email}"
type: mrkdwn
Primitive Input and Primitive List Output
Apex method:
public class StringListExample {
public static String[] echoMultiple(String string1, String string2, String string3) {
List<String> myList = new List<String>();
myList.add(string1);
myList.add(string2);
myList.add(string3);
return myList;
}
}
View:
description: "This is a simple list view containing an Apex echo list data provider"
schema:
properties:
title:
type: string
defaultValue: "EchoMultiple ApexDataProvider"
string1:
type: string
required: true
string2:
type: string
required: true
string3:
type: string
required: true
dataproviders:
echoStrings:
definition: "apex__StringListExample.echoMultiple"
properties:
string1: "{!view.properties.string1}"
string2: "{!view.properties.string2}"
string3: "{!view.properties.string3}"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: iteration # iterate through list of strings
properties:
foreach: "{!echoStrings}"
foritem: "echoStr"
components:
- definition: section
properties:
text: "{!echoStr}"
Map with Contact List Output
Apex method:
public class MapContactListExample {
publicstatic Map<Id, List<Contact>> getAccountContactMap() {
List<Contact> contacts = [
SELECT Id, Name, Title, Phone, Email, AccountId
FROM Contact
WITH SECURITY_ENFORCED
LIMIT 10
];
Map<Id, List<Contact>> contactMap = new Map<Id, List<Contact>>();
for (Contact contact : contacts) {
Id acctId = contact.AccountId;
if (!contactMap.containsKey(acctId)) {
contactMap.put(acctId, new List<Contact>());
}
contactMap.get(acctId).add(contact);
}
return contactMap;
}
}
View:
description: "This is a simple list view containing an Apex account contact map data provider"
schema:
properties:
title:
type: string
defaultValue: "Account Contacts ApexDataProvider"
dataproviders:
contacts:
definition: "apex__MapContactListExample.getAccountContactMap"
components:
- definition: modal
properties:
title: "{!view.properties.title}"
components:
- definition: header
properties:
text: "My Contacts for 001xx000003GYQRAA4"
- definition: iteration
properties:
foreach: "{!contacts.001xx000003GYQRAA4}"
foritem: "contact"
components:
- definition: divider
- definition: section
properties:
text: "{!contact.Name}"
- definition: section
properties:
text:
text: "*Id:* {!contact.Id}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Title:* {!contact.Title}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Phone:* {!contact.Phone}"
type: mrkdwn
- definition: section
properties:
text:
text: "*Email:* {!contact.Email}"
type: mrkdwn
tip: This example is from view_contact.view in the sample app.
External Select
Apex data provider using List<Slack.Option> and returning Slack.OptionDataResponse:
global class AccountDataProvider {
global static Slack.OptionDataResponse getAccountsByName(String value) {
String name = '%'+ value + '%';
List<Account> accounts = [
SELECT Id, Name
FROM Account
WHERE Name LIKE :name
WITH SECURITY_ENFORCED
LIMIT 10
];
System.debug('retrieved accounts');
List<Slack.Option> accountOptions = new List<Slack.Option>();
for(Account account: accounts) {
Slack.Option option = new Slack.Option(account.Name, account.Id);
System.debug(option.getText());
accountOptions.add(option);
}
return new Slack.OptionDataResponse(accountOptions);
}
}
Apex data provider using List<Slack.OptionGroup> and returning Slack.OptionDataResponse:
global class ContactDataProvider {
global static Slack.OptionDataResponse getContactGroupsByName(String value) {
String name = '%'+ value + '%';
List<Contact> contacts = [
SELECT Name, Id, AccountId, Account.name
FROM Contact
WHERE Name LIKE :name
LIMIT 10
];
Map<Id, List<Slack.Option>> contactsByAccount = new Map<Id, List<Slack.Option>>();
Map<Id, String> accountNames = new Map<Id,String>();
for(Contact contact: contacts) {
List<Slack.Option> options = contactsByAccount.get(contact.AccountId);
Slack.Option currentOption = new Slack.Option(contact.name, contact.id);
if (options == null) {
List<Slack.Option> newList = new List<Slack.Option>();
newList.add(currentOption);
contactsByAccount.put(contact.AccountId, newList);
accountNames.put(contact.AccountId, contact.Account.name);
} else {
options.add(currentOption);
}
}
List<Slack.OptionGroup> contactOptionGroups = new List<Slack.OptionGroup>();
for(Id key : contactsByAccount.keySet()) {
String accountName = accountNames.get(key);
System.debug(key);
Slack.OptionGroup optionGroup = new Slack.OptionGroup(accountName, contactsByAccount.get(key));
System.debug(optionGroup.getLabel());
contactOptionGroups.add(optionGroup);
}
return new Slack.OptionDataResponse(contactOptionGroups);
}
}
View:
description: "View with external select examples."
components:
- definition: modal
properties:
title: "External Select"
components:
- definition: section
properties:
text: "Select an Account"
- definition: actions
name: "external_select_accounts"
components:
- definition: externalSelect
properties:
placeholder: "Look up an account by name"
name: "account_lookup"
datasource:
definition: "apex__AccountDataProvider.getAccountsByName"
- definition: section
properties:
text: "Select a Contact"
- definition: actions
name: "external_select_contacts"
components:
- definition: externalSelect
properties:
placeholder: "Look up a Contact by name"
name: "contact_lookup"
datasource:
definition: "apex__ContactDataProvider.getContactGroupsByName"
tip: This example is from create_opportunity.view in the sample app.