One of the most requested Chatter features in Summer ’15 is the ability to edit posts and comments. While it’s an awesome feature in its own right, I discovered a delightful side effect while testing its API: you can write just a few lines of Apex code to preserve @mentions in triggers.
The Problem: Mentions Disappear in Triggers
Apex triggers are a powerful part of the Salesforce1 platform. One way to customize Chatter is to write a trigger that modifies the body of a feed item or comment when it’s posted.
For example, compliance apps that prevent certain words or phrases from being posted do exactly that: they substitute blocklisted words with replacement text like “*****”.
The drawback is that if there’s an @mention, it gets “stripped out” and displayed as plain text—the person or group you’re mentioning doesn’t get notified, which is a serious limitation.
To see the problem, let’s create a simple trigger that adds a disclaimer at the end of each post:
Before activating the trigger, a post with an @mention looks like this:
After activating the trigger to add the disclaimer, the @mention gets stripped out:
The root cause of the problem is that @mentions aren’t supported in the FeedItem and FeedComment sObjects. The only ways to use @mentions programmatically are with the Chatter REST API and the methods in the ConnectApi.ChatterFeeds Apex class. Until Summer ’15, there wasn’t a way to use the Apex methods to solve the trigger problem.
The Solution: Editing + ConnectApi = Mentions Preserved!
What I discovered is that you can call the following Apex methods from within an insert trigger to preserve @mentions:
In order for this to work, the “Allow users to edit posts and comments” Chatter setting must be on, and the “Edit my own posts” user profile permission must be enabled for all users who post to Chatter. This is very important. Any users who don’t have permission to edit their own posts will see errors when they attempt to post.
Create a Trigger
Add an after insert trigger on FeedItem (or FeedComment, if you want to edit comments). The trigger delegates to a helper class.
Create an Apex Helper Class
The helper class does all the work:
Makes a call to ConnectApi.ChatterFeeds.getFeedElementBatch() to get all the feed items passed into the trigger. It does this to get the message segments, which include any mention segments.
For each feed item:
Convert all the body’s message segments into input segments. (Tip: you can use the createFeedItemInputFromBody() method I added to my ConnectApiHelper class.)
Modify the input segments as you see fit.
Call ConnectApi.ChatterFeeds.updateFeedElement() with the modified input segments to update the feed item.
Here’s sample code for the helper class. Note that it depends on the ConnectApiHelper class that’s available on GitHub.
Since you call ConnectApi.ChatterFeeds.updateFeedElement() within the same transaction as the trigger, you see the changes immediately in the UI—there’s no need for a refresh.
Here’s the feed item that we showed you earlier, with a disclaimer added by a trigger that uses this technique. Notice that the timestamp says “Edited Today” because we edited it in the trigger. The @mention is preserved:
This is a simple example, but you can implement anything you like in your modifyInput() method. Want to always capitalize your company’s name? Prevent certain words from being posted? Add a hashtag whenever a certain word appears? It’s up to you.
Note that we haven’t included this technique in our documentation because we don’t offer official support for it. As with all triggers, the order in which the trigger gets fired among other after insert triggers (including those installed by AppExchange apps) is not predictable. Please keep this in mind when using this technique.
We hope this helps to improve your Chatter customizations!