📢 Attention Salesforce Certified Trailblazers! Maintain your credentials and link your Trailhead and Webassessor accounts by April 19th. Learn more.
close

Build a Rich Publisher App

Learning Objectives

After completing this unit, you’ll be able to:
  • List the interfaces and events provided in the Rich Publisher Apps platform.
  • Build a Rich Publisher App from scratch.
  • Configure Rich Publisher Apps in a Community.

Step 1. Upload Your Icon Image and Get Its File Asset ID

You’ve learned how community members interact with Rich Publisher App icons. As a developer, here’s how you upload the image and get its fileAsset ID.

Rich Publisher App icons in the question publisher

You use the fileAsset ID for the icon when you create the Chatter extension entity. Adding the fileAsset ID to ChatterExtension enables you to package the icon file with your app.

Note

Note

The Lightning Component framework has two programming models, Lightning Web Components and Aura. In this module, we build Rich Publisher Apps using Aura.

To get the fileAsset ID:

  1. Upload your icon file to Salesforce.
  2. Copy the file ID.
    Note

    Note

    You can get the file ID from file details in Salesforce. Go to the Files page, and view file details. Copy the file ID from your browser’s URL. It’s a long number, like 069R00000003roQ.

  3. Go to Workbench, and get the value for id under fileAsset.
    • In the REST Explorer, select Post, and enter the path: /services/data/v43.0/connect/files/[file_ID]/asset
    • For [file_ID], enter the file ID you copied in Step 2.
    • In the Request Body, enter {}.
    • Click Execute.

      A fileAsset ID in Workbench

    • Expand the fileAsset node, copy the value for id, and paste it somewhere for later user.

Step 2. Create Lightning Components for Composition and Rendering

When a community member clicks a Rich Publisher App icon, the action causes a composition modal to open. The modal contains a Lightning component. The Lightning component enables the user to select something, search for something, or generate something. You have the freedom to customize this component for your use case.

Let’s see how one company uses the Rich Publisher Apps platform to attach cases to posts and questions.

Meet Capricorn

Capricorn sells coffee and high-end coffee brewing equipment and prides itself on its customer service. One of its secrets is a community it set up for customer service agents to discuss open cases and collaborate on solutions. Capricorn wants to develop a Rich Publisher App for attaching cases to posts and questions. They want to give their agents a way to mine past solutions for quick resolutions in the present. Here’s what they do.

A. Create the First Lightning Component

Create a Lightning component that extends the Lightning interface lightning:availableForChatterExtensionComposer. The composition component uses this interface.

The Capricorn dev team uses an aura iteration to show list items in the component code. Here is the Lightning component code.

<aura:component implements="lightning:availableForChatterExtensionComposer" controller="caseController">
    <aura:handler name="init" value="{!this}" action="{!c.init}"/>
    
    <aura:attribute name="items" type="List" description="Contains a list of items for user to select."/>
    
    <div class="container">
        <aura:iteration items="{!v.items}" var="item" indexVar="index">
            <div class="itemContainer" onclick="{!c.selected}">
                <div class="itemLeft">
                	<img class="itemIcon" src="https://login.salesforce.com/logos/Standard/record/logo.svg"></img>
                </div>
                <div class="itemRight">
                    <div class="itemTitle">{!item.title}</div>
                	<div class="itemDescription">Case Number: {!item.caseNo}</div>
                </div>
            </div>
        </aura:iteration>
    </div>
</aura:component>

The Capricorn team makes an Apex request in the controller init function to fetch support case information for the selection list. Here is the controller code associated with the Lightning component.

({
	init : function(cmp, event, helper) {
        var action = cmp.get("c.getCases");
        action.setCallback(this, function(response) {
            var state = response.getState();
            if (state === "SUCCESS") {
                var caseList = [];
                var response = response.getReturnValue();
                for (var i=0;i<response.length;i++) {
                    caseList.push({
                        "title": response[i].Subject,
                        "caseNo": response[i].CaseNumber
                    })
                }
                cmp.set("v.items", caseList);
            }
        });
        $A.enqueueAction(action);
	},
    
    selected: function(cmp, event, helper) {
        var selectedItem = helper.getSelectedItem(cmp, event);
		var compEvent = cmp.getEvent("sendChatterExtensionPayload");
		compEvent.setParams({
			"payload" : helper.getPayload(selectedItem),
			"extensionTitle" : helper.getTitle(selectedItem),
			"extensionDescription" : helper.getDescription(selectedItem)
		});
		compEvent.fire(); 
    }
})

Here is the helper code to go along with the controller.

({  
    getSelectedItem: function(cmp, event) {
        var clicked = event.currentTarget;
        var parent = clicked.parentElement;
        var total = parent.children.length;
        var selectedIndex = -1;
        for(var i=0; i<total; i++) {
            if(clicked === parent.children.item(i)) {
                selectedIndex = i;
            }
            $A.util.removeClass(parent.children.item(i), "selected");
        }
        $A.util.addClass(clicked, "selected");
        
        var selectedTh = cmp.get("v.items")[selectedIndex];
        return selectedTh;
    },
    
    getPayload: function(item) {
        return item;
    },
    
    getTitle: function(item) {
        return item.title;
    },
    
    getDescription: function(item) {
        return item.caseNo;
    }
})
Tip

Tip

Here’s one way to write an Apex call for the getCases function.

public class caseController {
    
    @AuraEnabled
    public static List<Case> getCases() {
       List<Case> cases = [SELECT AccountId,CaseNumber,Subject,Description,Id FROM Case ORDER BY CreatedDate ASC NULLS FIRST LIMIT 20];
       return cases;
    }
}

You can implement your own way for users to make a selection. You can have any logic in Apex for getting smart or fresh data using internal or third-party services to build powerful Rich Publisher Apps.

The important thing is to make sure that a user-click triggers the aura event lightning:sendChatterExtensionPayload in the controller code. In Capricorn’s code sample, the team set up the event in the selected function. Setting the event in the selected function sends the payload to associate with the feed item when the user makes a selection.

The team sets the extensionTitle and extensionDescription metadata using helper functions to associate with the payload. This metadata is for non-Lightning use cases, like email notifications or Classic view. Optionally, you can also add a thumbnail URL.

Here is a modal with a title and thumbnails.

List items in a composer component

The Rich Publisher Apps platform also provides the Add and Cancel buttons. In the previous image, the Add button is disabled. Salesforce enables the Add button only after the lightning:sendChatterExtensionPayload event is fired with a non-empty payload. If the event is fired with an empty payload, then the button stays disabled.

Enabled Add button

B. Create the Second Lightning Component

Next, the Capricorn team creates a Lightning component that extends the Lightning interface lightning:availableForChatterExtensionRenderer. This interface renders the selected payload in the publisher when the FeedItem is rendered. There are two essential attributes as part of this interface: variant and payload. The variant attribute lets you decide how to render something based on whether the selected app is previewed in the publisher or rendered in the FeedItem. The payload attribute is the JavaScript Object that the user selected in the composition component.

<aura:component implements="lightning:availableForChatterExtensionRenderer">
    
    <div class="container">
        <a target="_blank" href="{!v.payload.url}">
            <div class="{! (v.variant == 'FEED' ? 'itemContainerBorder' : '') + ' itemContainer'}">
                <div class="itemLeft">
                    <img class="itemIcon" src="{!v.payload.icon}"></img>
                </div>
                <div class="itemRight">
                    <div class="itemTitle">{!v.payload.title}</div>
                    <div class="itemSubtitle">{!v.payload.subtitle}</div>
                    <div class="itemDescription">Case Number: {!v.payload.caseNo}</div>
                </div>
            </div>
        </a>
    </div>

</aura:component>

Capricorn uses the variant FEED to decide which CSS class to use. The use of FEED signals Salesforce to render the Rich Publisher App in a FeedItem. To render the app in the publisher, use the variant PREVIEW. The payload information shows which case to render. In this example, the payload is static. But you can also use server-side Apex controllers to get live, dynamic information inside your renderer component.

Here’s how the payload looks as a preview inside the publisher (PREVIEW):

Preview of a Rich Publisher App payload

Here’s how the payload looks in the final rendered feed item (FEED):

Rich Publisher App payload published with a feed item

Step 3. Create a Rich Publisher App in Workbench

After you create the Lightning components and have the fileAsset ID, create the Rich Publisher App in Workbench.

Go to Workbench, and insert a ChatterExtension object (Workbench > Data > Insert > ChatterExtension). Then associate all your component values with ChatterExtension fields.

Tip

Tip

One way to get component values is to go to Setup and search for Lightning Components. Click a listed component to view its details. Copy the component ID from the browser URL.

The ChatterExtension object

  • Provide the Lightning component ID for the composition component.
  • Add text for the modal header.
  • Add hover text for the app icon (the icon that appears in the feed publisher).
  • Provide the fileAsset ID for the app icon.
  • Provide the Lightning component ID for the render component.
  • For Type enter Lightning. Currently, Lightning is the only type available.
Note

Note

You can localize header and hover text in Translation Workbench.

Step 4. Enable Rich Publisher Apps in Your Community

When everything’s ready to go, the Capricorn team adds the app to the feed publisher in their community. You can add up to five Rich Publisher Apps to your community through the Administration Workspace in Community Workspaces.

  1. Go to Community Workspaces, and click the Administration tile.
  2. Click Rich Publisher Apps in the navigation column.
  3. Select up to five apps from the Available Apps column, and move them to the Selected Apps column.

    Rich Publisher Apps in the Administration Workspace]

  4. To set the order for the icons to appear in the publisher, move selected apps up or down the list.
  5. Click Save.
retargeting