Salesforce
Overview
⚠️ Note that the following sections are relevant only for the latest versions of the Salesforce Adapter (5.0 and later). For details on the legacy versions (3.0 and 4.0), see the Legacy Adapter section.
After installing the Salesforce Adapter in your organization, you can start interop-enabling your Lightning Web Components. If you intend on using Salesforce within the io.Connect Platform (io.Connect Desktop or io.Connect Browser), it's recommended to use the InteropConnectedComponentStandalone
component that is distributed with the Salesforce Adapter package, as it provides the best possible interoperability performance for this case. This component can be used both in your Lightning Our apps, or from within the Salesforce platform (with certain limitations).
⚠️ Note that using Salesforce within the io.Connect Platform has the advantage of not having to attach an io.Connect Utility Bar component to your Lightning App and not having to provide additional package configuration after installation in order to enable interoperability. These steps, however, are required when using Salesforce in a web browser.
⚠️ Note that using the
InteropConnectedComponentStandalone
component to achieve interoperability between Salesforce and io.Connect Browser projects is still an experimental feature. This means that enabling some of the io.Connect Browser functionalities may require additional development.
Requirements
To use Salesforce within the io.Connect platform, you must provide a valid app definition for Salesforce and enable auto injection of the @interopio/desktop
library. For instructions on how to create an app definition for io.Connect Desktop and io.Connect Browser projects, see the Salesforce App Definition section.
To be able to use the InteropConnectedComponentStandalone
component, Lightning Web Security must be enabled:
Log in to your Salesforce organization as an administrator.
Go to
Setup > Security > Session Settings
.Make sure that Lightning Web Security is enabled in the "Lightning Web Security" section.
Limitations
There are certain limitations if the InteropConnectedComponentStandalone
is used from inside the Salesforce platform:
Due to the security restrictions imposed by Salesforce, it's impossible to achieve interoperability between interop-enabled LWCs in Salesforce and io.Connect Browser. To avoid this limitation, it's recommended to use the
InteropConnectedComponentStandalone
component in Lightning Out apps or Visualforce pages instead.If using more than one instance of the component, all interop-enabled LWCs will have the same application name. This means that you won't be able to register more than one event listener for the same type of event. To avoid this limitation, it's recommended to use the
InteropConnectedComponentStandalone
component in Lightning Out apps instead.
Examples
Full working examples demonstrating interoperability between Salesforce and interop-enabled apps are provided via the interop.io Salesforce Adapter [demos]
Salesforce package.
To retrieve the package into your project, execute the following command using the Salesforce CLI:
sf project retrieve start --package-name "interop.io Salesforce Adapter [demos]"
Salesforce App Definition
To be able to use Salesforce within the io.Connect platform, you must provide a valid app definition for it. The following sections describe how to create an app definition for Salesforce depending on whether it's running in io.Connect Desktop or in io.Connect Browser.
io.Connect Desktop
To be able to open Salesforce in io.Connect Windows or Workspaces in io.Connect Desktop, you must provide a valid app definition for it. Besides the standard required definition properties ("name"
, "type"
, and "url"
), the only other requirement is to enable auto injection of the @interopio/desktop
library. This is necessary, because the library provides the interoperability capabilities of the InteropConnectedComponentStandalone
component.
The following is an example configuration for defining Salesforce as an io.Connect app:
{
"name": "salesforce",
"type": "window",
"title": "Salesforce",
"details": {
// URL pointing to your Salesforce organization.
"url": "https://your-salesforce-url.salesforce.com/",
// Enable auto injection of the `@interopio/desktop` library.
"autoInjectAPI": {
"enabled": true
}
},
"customProperties": {
// Use this if you want to add Salesforce to the "Add App" menu in a Workspace.
// This will enable users to open Salesforce in Workspaces.
"includeInWorkspaces": true
}
}
io.Connect Browser
To be able to open Salesforce in io.Connect Windows or Workspaces in io.Connect Desktop, you must provide a valid app definition for it when initializing your Main app.
The following is an example configuration for defining Salesforce as an io.Connect app:
import IOBrowserPlatform from "@interopio/browser-platform";
const config = {
licenseKey: "my-license-key",
applications: {
local: [
{
name: "salesforce",
type: "window",
title: "Salesforce",
details: {
// URL pointing to your Salesforce organization.
url: "https://your-salesforce-url.salesforce.com/"
},
customProperties: {
// Use this if you want to add Salesforce to the "Add App" menu in a Workspace.
// This will enable users to open Salesforce in Workspaces.
includeInWorkspaces: true
}
}
]
}
};
const { io } = await IOBrowserPlatform(config);
Usage
The following sections describe the InteropConnectedComponentStandalone
component API and provide examples on how to implement an interop-enabled LWC.
Component API
The InteropConnectedComponentStandalone
component provides a set of properties and methods that you can use to interop-enable your LWC.
The component has the following properties that can be used in its HTML file:
Property | Type | Description |
---|---|---|
application-name |
string |
Name for the component that will be used by the io.Connect framework when interacting with other interop-enabled apps. |
factory-config |
object |
Config object passed to the IODesktop() factory function for initializing the @interopio/desktop library or a Config object passed to the IOBrowser() factory function for initializing the @interopio/browser library depending on the io.Connect platform your are using. Defaults to {} . |
connected-methods |
object |
Key/value pairs of Interop method names and the names of the DOM events that they will handle (e.g., { "My.Method": "my_event" } ). If you specify this property, you must also specify the events that will be handled. |
oninterop_<event-name> |
function |
Defines a DOM event to be handled by one of the Interop methods specified in the connected-methods property. The property name must always be prefixed with oninterop_ (e.g., oninterop_my_event ). Accepts as a value the component hook that is defined as the handler for the respective Interop method. You can define as many DOM events as necessary. |
The component has the following methods that can be accessed via the this.connectedBase
object upon successful connection to the io.Connect framework:
Method | Accepts | Description |
---|---|---|
executePlatformMessageCallback() |
(string, boolean, object) |
Use this method to send a response to the InteropConnectedComponentStandalone component about the result from the Interop method invocation. The component will relay the response to the calling app. Accepts three required arguments - the ID of the invocation (which can be extracted from event details), a Boolean value denoting whether the invocation Promise should be resolved (true ) or rejected (false ), and the actual result from the method invocation to be passed to the calling app. |
registerMethod() |
(string, string) |
Can be used instead of the connected-methods property to register Interop methods for handling DOM events. Accepts as required arguments the name of the Interop method and the name of the DOM event. |
triggerOutbound() |
(object) |
Invokes an Interop method registered by other interop-enabled apps. Accepts as a required argument an object with method and payload properties specifying the name of the Interop method to invoke and arguments for the invocation. |
unregisterMethod() |
(string) |
Unregisters an Interop method. Accepts as a required argument the name of the Interop method to unregister. |
verifyExistingExternalRegisteredMethod() |
(string) |
Verifies whether an Interop method is registered within the io.Connect framework. Use this method before invoking an Interop method registered by another interop-enabled app. Accepts as a required argument the name of the Interop method to verify. |
Using io.Connect APIs
⚠️ Note that using the io.Connect APIs in your interop-enabled component must always be executed via the
onConnected()
hook to ensure connectivity to the io.Connect framework.
The io.Connect APIs provided by the initialized @interopio/desktop
or @interopio/browser
libraries can be accessed directly in your interop-enabled component. This enables you to use all functionalities they provide in addition to the APIs provided by the InteropConnectedComponentStandalone
component.
The io.Connect APIs can be accessed only after a successful connection to the io.Connect framework has been established. To ensure this is the case, always route the usage of io.Connect APIs via the onConnected()
hook of your component.
Example Implementation
To interop-enable your LWC, you must:
- create a standard LWC with XML, HTML, and JavaScript files;
- use the
InteropConnectedComponentStandalone
component in the HTML file to wrap your LWC; - define the required component properties (
application-name
andfactory-config
) in the HTML file; - use the
InteropConnectedComponentStandalone
component API and the io.Connect APIs to implement the component functionality;
The following examples demonstrate how to create an interop-enabled LWC that will be used in an io.Connect Desktop platform. The component registers an Interop method that can be invoked by other interop-enabled apps, and also invokes an Interop method already registered by other interop-enabled apps.
Example XML configuration for a LWC:
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>60.0</apiVersion>
<isExposed>true</isExposed>
<description>This component demonstrates inbound and outbound interoperability between Salesforce and io.Connect apps.</description>
<masterLabel>My Interop-Enabled Component</masterLabel>
<targets>
<!-- Salesforce pages targeted by the component. -->
<target>lightning__RecordPage</target>
<target>lightning__AppPage</target>
<target>lightning__HomePage</target>
</targets>
</LightningComponentBundle>
Example HTML structure of an interop-enabled LWC that uses the InteropConnectedComponentStandalone
component:
<template>
<!-- Using the `InteropConnectedComponentStandalone` component to interop-enable your LWC. -->
<Tick42-interop-connected-component-standalone
application-name="my-interop-enabled-component"
factory-config={myCustomIODesktopConfig}
connected-methods={interopMethods}
oninterop_inbound_event={onInbound}
>
<lightning-card title="My Interop-Enabled Component">
<!-- Your component structure. -->
</lightning-card>
</Tick42-interop-connected-component-standalone>
</template>
Example implementation of an interop-enabled LWC:
// Import the `InteropConnectedComponentStandalone` component.
import InteropConnectedComponentStandalone from "Tick42/interopConnectedComponentStandalone";
export const TEST_INBOUND_METHOD = "My.Test.Inbound.Method";
export const TEST_OUTBOUND_METHOD = "My.Test.Outbound.Method";
export const INTEROP_METHODS = {};
// Interop method definitions.
// For each method, it's required to specify a method name and the DOM event that it will handle.
INTEROP_METHODS[TEST_INBOUND_METHOD] = {
// Optional display name and description for the method. Can be used in the UI.
displayName: "Inbound",
description: "Inbound Interop method.",
// Holds arguments for the method invocation.
// Not used in the example, defined here only for demonstrative purposes
// (invocation arguments are usually provided by the calling app).
payload: { value: "value" },
// Method name.
method: TEST_INBOUND_METHOD,
// Name of the event that the method will handle.
domEvent: "inbound_event"
};
export default class MyInteropEnabledComponent extends InteropConnectedComponentStandalone {
_interopMethods = INTEROP_METHODS;
// Custom configuration for initializing the `@interopio/desktop` library.
myCustomIODesktopConfig = { windows: false, appManager: false };
// This will pass the Interop methods and the respective DOM events
// to the `connected-methods` property of the `InteropConnectedComponentStandalone` component.
get interopMethods() {
const result = {};
// Extracting the method name and the name of the event that it will handle.
// The specified methods will be invoked automatically when the respective events are fired.
Object.values(this._interopMethods).forEach((m) => {
result[m.method] = m.domEvent;
});
return result;
};
disconnectedCallback() {
super.disconnectedCallback();
};
renderedCallback() {
// Check whether a successful connection to the io.Connect framework has been established.
if (this.connectedBase) {
return;
};
super.renderedCallback();
};
// This will be called by the `InteropConnectedComponentStandalone` component
// on successful connection to the io.Connect framework.
// Once connected, you will have access to the component API via the `this.connectedBase` object
// and to the io.Connect APIs via the `this.io` object.
onConnected() {
super.onConnected();
// Invoke an outbound Interop method.
this.triggerOutbound();
};
// Implementation of the handler for the `TEST_OUTBOUND_METHOD` method that will be invoked for the `inbound_event`.
onInbound(event) {
// Extract the invocation ID and the arguments for the Interop method invocation provided by the calling app.
const { callbackID, payload: { value } } = event.detail;
// If `true`, the `InteropConnectedComponentStandalone` component will resolve the invocation `Promise`.
// If `false`, the `InteropConnectedComponentStandalone` component will reject the invocation `Promise`.
const isSuccessful = value ? true : false;
// Result that will be returned from invoking the Interop method.
const invocationResult = { "OK": value ? true : false };
// Send a response to the `InteropConnectedComponentStandalone` component.
// The `InteropConnectedComponentStandalone` component will relay the response to the calling app.
this.connectedBase.executePlatformMessageCallback(callbackID, isSuccessful, invocationResult);
console.log(`Inbound data received: ${value}.`);
};
triggerOutbound() {
// Checking whether the desired Interop method has been registered by any io.Connect app.
isRegistered = this.connectedBase.verifyExistingExternalRegisteredMethod(TEST_OUTBOUND_METHOD);
// Skip the invocation if the Interop method hasn't been registered.
if (!isRegistered) {
return;
};
// Providing the name of the Interop method to invoke and arguments for the invocation.
const args = {
method: TEST_OUTBOUND_METHOD,
payload: { value: "value" }
};
// Invoke an outbound Interop method.
// Alternatively, you can use the io.Connect API directly: this.io.interop.invoke(args.method, args.payload);
this.connectedBase.triggerOutbound(args);
};
};