Chatter Series – Chatter Connect (Chatter in Apex)
In my previous blog, on a high level, I described what Chatter is and all the components involved with Chatter. This blog will focus more on building custom Chatter components.
The Why?
Chatter Connect comprises Chatter REST API and Chatter in Apex.
Use Chatter REST API to integrate mobile apps, intranet sites, and 3rd party Web applications with Salesforce. Chatter REST API provides resources for feeds, comments, likes, users, groups, private messages, recommendations, topics, and more. Chatter REST API is on by default in all organizations and editions that have Chatter.
Use Chatter in Apex to create custom experiences in Salesforce. Many Chatter REST API resource actions are exposed as static methods in Apex classes in the ConnectApi namespace. These classes are called Chatter in Apex. Chatter in Apex is available in all organizations and editions that have Apex enabled.
My series will go into detail on Chatter in Apex, in other words, the ConnectApi namespace. If you are too busy to go over the details and want just code, please navigate to my Github Repo.
Chatter Feed
The ConnectApi namespace is logically categorized into input and output classes. As the names suggest, anything that helps in retrieving or displaying the Chatter feed, likes, replies etc. uses output classes. Any action (e.g., posting a feed, liking a post, replies, etc.) that is performed by the User on Chatter and is written to the Database uses input classes.
NOTE: with Salesforce API Version 32.0 and above, there are many changes in the structure of the ConnectApi classes. Please make sure that you use v32.0 or above when using my code from the blog.
Output Classes
The image above gives an overview of the structure of Chatter Output Classes that I will be using in the code, (FeedElementPage). A Chatter post is a list of FeedElements that are part of FeedElementPage.
Note: For a comprehensive list of Chatter classes, please click here.
The main method that is used to retrieve the Chatter feed is getFeedElementsFromFeed. Below is a code sample to get the feed. There are many overloaded versions of the same method with various arguments. In the code below, the first argument is communityId or NetworkId, the second is the type of Feed (in our case Record enum), and the third is the groupId.
[code language=”java”]
ConnectApi.FeedElementPage feedElementPage = ConnectApi.ChatterFeeds.getFeedElementsFromFeed(communityId,ConnectApi.FeedType.Record,groupid);
return feedElementPage;
[/code]
Now that we have the feeds, all we need to do is display them on a page. I am using Handlebars.js, Handlebars.js is a templating library that allows us to create semantic templates. This way it’s much cleaner and our JavaScript and HTML are truly decoupled.
The Handlebar template below displays the list of feeds on a Visualforce page with Bootstrap styling.
[code language=”javascript”]
{{#if elements.length}}
<ul class=”media-list”>
<ul class=”media-list”>{{#each elements}}
<li class=”media”>
<div class=”media-left”><a href=”#”>
<img class=”media-object” style=”height: 50px;” src=”{{actor.photo.smallPhotoUrl}}” alt=”{{actor.name}}” />
</a></div>
<div class=”media-body”>
<h3 class=”media-heading” style=”font-size: 18px; color: #015ba7;”><span style=”color: #000000;”>{{actor.name}}</span></h3>
{{#each body.messageSegments}}
{{#isTextSegment type}}
{{text}}
{{/isTextSegment}}
{{#isMentionSegment type}}
<a href=”#”>{{record.displayName}}</a>
{{/isMentionSegment}}
{{/each}}
<div class=”media-footer”><a class=”postfeed-comment” style=”font-size: 12px;” href=”#”>Comment</a>
{{#if capabilities.chatterLikes.isLikedByCurrentUser}}
<a class=”postfeed-like unlikeBtn” style=”font-size: 12px;” href=”#”>Unlike</a>
{{else}}
<a class=”postfeed-like likeBtn” style=”font-size: 12px;” href=”#”>Like</a>
{{/if}}
<em style=”font-size: 12px;”> {{dateFormat createdDate}} </em></div>
{{#if capabilities.chatterLikes.likesMessage}}
<div class=”like-footer”><em style=”font-size: 12px;”>{{capabilities.chatterLikes.likesMessage.text}}</em></div>
{{/if}}
{{#each capabilities.comments.page.items}}
<div class=”media”>
<div class=”media-left”><a href=”#”>
<img class=”media-object” style=”height: 40px;” src=”{{user.photo.smallPhotoUrl}}” alt=”{{user.name}}” />
</a></div>
<div class=”media-body”>
<h4 class=”media-heading” style=”font-size: 16px;”>{{user.name}}</h4>
{{#each body.messageSegments}}
{{#isTextSegment type}}
{{text}}
{{/isTextSegment}}
{{#isMentionSegment type}}
{{record.displayName}}
{{/isMentionSegment}}
{{/each}}
<div class=”media-footer”><a class=”postfeed-like” style=”font-size: 12px;” href=”#”>Like</a>
<em style=”font-size: 12px;”> {{dateFormat createdDate}} </em></div>
</div>
</div>
{{/each}}
</div>
<div class=”comment body”><textarea id=”reply_{{id}}” class=”form-control sharearea” rows=”1″></textarea>
<button id=”replybtn_{{id}}” class=”btn btn-alt btn-comment pull-right btn-sm replybtn”>
Reply
</button></div></li>
</ul>
</ul>
{{/each}}
{{/if}}
[/code]
I am using JavaScript remoting on document ready, which calls the controller’s getFeedData method (as shown above) that returns a FeedElementPage object.
[code lang=”javascript”]
function getFeedsForGroup() {
// Call the @RemoteAction JavaScript function
Visualforce.remoting.Manager.invokeAction(
‘{!$RemoteAction.ChatterFeedController.getFeedData}’,
‘{!subjectid}’, function(result, event) {
console.log(‘result’);
console.log(result);
feedItems = result.elements;
console.log(feedItems);
buildTemplate();
});
}
function buildTemplate() {
var record_data = {“elements”:feedItems};
var result_html = feedTemplate(record_data);
$(‘#comments’).html(result_html);
}
[/code]
Thats it. Now we have a page that displays the list of Chatter Posts. Isn’t it fun? In the next post, we will go over the input classes that record a feed, a like, a reply, mentions. Until then, happy coding 🙂