A Step-by-Step Guide to Implement Tagging in Forums
In this blog, Sreeja Paul, Software Developer @ GeekyAnts, explores implementing tagging in platforms with react-mentions.
Table of contents
Tagging functionality enhances user interaction by allowing direct mentions, improving communication, collaboration, and visibility within platform.
Tagging functionality in comments is a powerful feature that enhances user interaction on platforms by allowing users to directly mention and engage with each other. Implementing this feature requires a comprehensive approach that involves both frontend and backend development. In this blog post, we will delve into the detailed process of how we successfully implemented tagging functionality. By examining the steps we took and the tools we used, you will gain a clear understanding of how to add this interactive element to your own applications.
Reference
To understand how tagging works, we commented with a tagged user on a post in Twitter and commented under a video / a comment in Youtube. Then we inspected the network tab to see the payload and response in the browser's developer tools. This gave us an understanding of how tagging in comment works. While implementing, we have modified the tagging structure as per our requirement and convenience.
To seamlessly implement tagging feature in comments, we have followed the steps discussed below.
Frontend Implementation
- Fetch the users list to tag: We have implemented the
react-mentions
package to implement the tagging feature in the frontend. When a user types ‘@’ followed by some characters of the username(whom the user wants to be tagged) without spaces or breaking character, one API call (1st pointer mentioned in the ‘Backend Implementation’ section) is being made, with debounce, with the text written after ‘@’(until a space or breaking character is encountered), as a query parameter. As a success response of this API, we get a list of users who have their name started with the passed query parameter. Then the list of matched users is rendered in a dropdown. All these became easy as we have used parameters like trigger(to get the mentioned name after ‘@’), data(to feed the users list, received from the API response, to the component), renderSuggetion(to render the users list in a dropdown) in the ‘Mention’ component of this package.
Append tagged user in the desired format: If the user selects any option from the dropdown, we are doing two things:
- In the existing raw comment’s text, we are appending the tagged user details in
<userName|userId>(userId is in uuid form)
format. We need this formatting, so that in the backend, we can segregate theuserName
, anduserId
, and can send the notification for the desired user. In this case a sample comment text looks like this:
- In the existing raw comment’s text, we are appending the tagged user details in
<Tester|d6bc01e6-1d74-43f9-abc3-cab7366c5c04>comment test
We highlight the selected username. It looks like this:
If the user does not select any user from the dropdown, we append the tagged user part as @name with the existing raw comment text, also as per UI no highlighting happens. This @name is then treated as a normal text, not a tagged user.
Upload the comment: When the user uploads the comments, we are calling an API(2nd pointer mentioned in the ‘Backend Implementation’ section) for that. In that API, we pass userId who has made the comment(eventually the user who has tagged others), contentId(in which the comment is made), and raw comments text(which has formatted tagged user info).
Update in the UI, after uploading the comment: Once the comment upload is successful, we get the raw comment text(which has formatted tagged user info) , along with other comment information as a response in the frontend. Then, we just parse the ‘userName’ from <userName|userId> format, and append a ‘@’ before the parsed userName, and render that with styling. It looks like:
Show notification to the tagged user: Once comments upload is successful, under the hood, the 4th pointer mentioned in the ‘Backend Implementation’ section gets executed. Now, if the tagged user opens their notification tab, they will call an API(5th pointer mentioned in the ‘Backend Implementation’ section) to fetch all the notifications available for them. In the list of notifications, the tagging in comment notification also should be visible.
Backend Implementation:
We have integrated Hasura into our backend to generate GraphQL APIs, implement role-based access control, and utilize actions and event triggers to handle custom business logic which significantly enhances our development efficiency. We have added couple of actions, mutations, event triggers to fulfill the tagging functionality:
- Added action to fetch users to tag: We have created an action named getListOfUsersToTag, on invocation of which, an HTTP request is triggered to the configured webhook URL(a custom API endpoint) with the specified query parameter(userName).
As a result from the webhook endpoint of the action getListOfUsersToTag
, a list of maximum 10 users with user details (id, name, profile photo), who have their name started with the passed query parameter is returned.
Added mutation to add or update comment: We have created mutations to add and update comments of the users in the comments table. These mutations store raw comments text to the message column of the comments table.
Added mutation to add notification: We have created a mutation to add an entry in the notifications table with proper details for a particular user(to whom the notification will be visible), which will be shown in the notification tab in the frontend.
Added event trigger to send notifications: We have added an event trigger
notify_for_tagged_comment
, which gets triggered on insert of a new entry and on update of the message column of any entry in the comments table. On trigger of any of the database events mentioned above, an HTTP request is invoked to the configured webhook URL(a custom API endpoint) with the relevant data.
To send notification for tagging we need to create an entry in the notifications table. In this notification table, we need to store the userId, userName and profilePicture of the user who has tagged others, contentId (in which the comment is made), commentMessage, commentId in an object in data column in JSONB format, and tagged userId(to whom the notification will be shown) in userId column.
In the custom API endpoint of the event trigger, we can access the new and updated comment entry details from the comments table. This entry of the comments table has userId who has made the comment(eventually the user who has tagged others), contentId, raw comments text as the ‘message’ column value(in the add or update mutation we have stored the same), commentId. With this userId (who has made the comment) we can run a GraphQL query to fetch the userName and profilePicture. At this point we can create the object notificationData, which needs to be stored in the data column in the notifications table. Now, the only thing which is remaining is to find out the tagged userId(s). For that, we have parsed the message column value, so that we get the matched patterns like <userName|userId>
(userId is in uuid form) and patterns like @username or normal text will be ignored. We have used regex pattern for this:
const regexPattern = /<([^|]+)\|([^>]+)>/g;
const matches = [...newCommentData['message'].matchAll(regexPattern)]; //Get array of matched pattern like <userName|userId>, patterns like @userName or normal comment text will be ignored by this
In the raw message text, if no match found like <userName|userId>(userId is in uuid form), then there is nothing to add in the notifications table, as no valid tagging is present in the message, but if some matches are found, then the ‘matches’ array looks like this(this is the array of tagged users with their userName
, and userId
):
[
["<userName1|uuidOfUser1>", "userName1", "uuidOfUser1"],
["<userName2|uuidOfUser2>", "userName2", "uuidOfUser2"]
]
If the length of the ‘matches’ array is more than 0, then we just loop through the array. With each loop we can access the userId(matches[i][2]) of the tagged user and add an entry with this tagged userId
and notificationData
object, in the notifications table via the previously defined mutation(In 3rd pointer).
- Added query to fetch notifications for a specific user: We have created a query to fetch the notifications from the notifications table, for a specific user(the logged in userId, who will hit this API). The response of this API, will be shown in the notification tab of that logged in user in the frontend.
This is how we implemented tagging functionality.
Conclusion
Incorporating tagging functionality into your comments system can significantly improve user engagement and interaction on your platform. By leveraging tools like react-mentions
for the frontend and Hasura for backend operations, we were able to create a seamless and efficient tagging system. Our approach, which involved inspecting network payloads on social media platforms, customizing tagging structures, and utilizing GraphQL APIs, ensured that our implementation was robust and user-friendly. We hope that this detailed guide provides you with the insights and techniques needed to implement tagging functionality in your own projects, enhancing the overall user experience.