
November 18, 2025 08:48 by
Peter
Key Functional Requirements
Users can type comments.
Auto-suggestions appear when typing @ for users.
Auto-suggestions appear when typing # for tags.
Comments should highlight mentions and hashtags.
Backend must store extracted mentions and tags.
Display comments with clickable mentions and hashtags.
Should support comment editing and deletion.
High-Level Workflow
User types comment →
Detect @mention or #tag →
Show suggestion list →
User selects item →
Submit comment →
Backend processes comment →
Save comment, mentions, tags →
Return formatted comment →
Display in UI
Sequence Diagram
User → Angular UI: Type comment
Angular UI → SuggestionService: Detect @ or #
SuggestionService → API: Fetch matching users or tags
API → Angular: Return suggestions
User → Angular: Select mention/tag
User → Angular: Submit final comment
Angular → API: Send comment text
API → Parser: Extract @mentions and #tags
Parser → DB: Save comment, mentions, tags
DB → API: Confirm save
API → Angular: Return formatted comment
Angular → User: Show updated comment list
Frontend Implementation (Angular)
Detecting Mentions and Hashtags in Textbox
<textarea
[(ngModel)]="commentText"
(keyup)="onKeyUp($event)"
placeholder="Write a comment...">
</textarea>
<div *ngIf="showSuggestions">
<ul class="suggestions">
<li *ngFor="let item of suggestions"
(click)="selectSuggestion(item)">
{{ item.display }}
</li>
</ul>
</div>
TypeScript Logic
onKeyUp(event: KeyboardEvent) {
const text = this.commentText;
const cursorPos = (event.target as HTMLTextAreaElement).selectionStart;
const charBeforeCursor = text[cursorPos - 1];
if (charBeforeCursor === '@') {
this.loadUserSuggestions();
}
if (charBeforeCursor === '#') {
this.loadTagSuggestions();
}
}
loadUserSuggestions() {
this.api.getUsers().subscribe(res => {
this.showSuggestions = true;
this.suggestions = res.map(u => ({ display: u.displayName, type: 'user', id: u.userId }));
});
}
loadTagSuggestions() {
this.api.getTags().subscribe(res => {
this.showSuggestions = true;
this.suggestions = res.map(t => ({ display: t.tagName, type: 'tag', id: t.tagId }));
});
}
selectSuggestion(item: any) {
const prefix = item.type === 'user' ? '@' : '#';
this.commentText += prefix + item.display + ' ';
this.showSuggestions = false;
}
Submitting the Comment
submitComment() {
this.api.postComment({ content: this.commentText }).subscribe(() => {
this.commentText = '';
this.loadComments();
});
}
Backend Implementation (ASP.NET Core)
Extracting Mentions and Tags
var mentions = Regex.Matches(model.Content, @"@(\w+)");
var tags = Regex.Matches(model.Content, @"#(\w+)");
API Controller
[HttpPost("comments")]
public async Task<IActionResult> PostComment(CommentDto model)
{
var comment = new Comment
{
UserId = model.UserId,
Content = model.Content,
CreatedOn = DateTime.UtcNow
};
_db.Comments.Add(comment);
await _db.SaveChangesAsync();
// Extract mentions
var mentions = Regex.Matches(model.Content, @"@(\w+)")
.Select(m => m.Groups[1].Value)
.ToList();
foreach (var m in mentions)
{
var user = _db.Users.FirstOrDefault(u => u.DisplayName == m);
if (user != null)
{
_db.CommentMentions.Add(new CommentMention
{
CommentId = comment.CommentId,
MentionedUserId = user.UserId
});
}
}
// Extract hashtags
var tags = Regex.Matches(model.Content, @"#(\w+)")
.Select(m => m.Groups[1].Value)
.ToList();
foreach (var t in tags)
{
var tag = _db.Tags.FirstOrDefault(x => x.TagName == t)
?? new Tag { TagName = t };
_db.CommentTags.Add(new CommentTag
{
CommentId = comment.CommentId,
TagId = tag.TagId
});
}
await _db.SaveChangesAsync();
return Ok();
}
Displaying Mentions and Hashtags with Highlighting
Angular Pipe
transform(value: string): string {
value = value.replace(/@(\w+)/g, `<span class="mention">@$1</span>`);
value = value.replace(/#(\w+)/g, `<span class="hashtag">#$1</span>`);
return value;
}
UI Styling
.mention { color: #0275d8; font-weight: bold; }
.hashtag { color: #5cb85c; font-weight: bold; }
.suggestions { list-style: none; margin: 0; padding: 0; background: #f5f5f5; }
.suggestions li { padding: 6px; cursor: pointer; }
Best Practices
- Use caching for user and tag suggestions to improve performance
- Avoid over-querying the database
- Rate-limit comment submission
- Support soft delete for comments
- Implement pagination for comment lists
- Add real-time support using SignalR if needed
Conclusion
A comment system with mentions and hashtags adds professional collaboration capabilities to any web application. By using Angular for real-time processing and ASP.NET Core for strong backend parsing, you can build a scalable and reusable module. The design shown here works for enterprise portals, task management systems, social feeds, project tracking tools, LMS platforms, and more.
European Best, cheap and reliable ASP.NET Core 10.0 hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.
