Mention Support in ASP.NET CORE Markdown Editor Control

17 Mar 202520 minutes to read

By integrating the Mention control with the Markdown Editor, users can effortlessly mention or tag other users or objects from a suggested list. This eliminates the need to manually type out names or identifying information, improving both efficiency and accuracy.

Enabling Mention in ASP.NET CORE Markdown Editor

To enable the Mention functionality within the Markdown Editor, set the target property of the Mention control to the ID of the textarea element inside the editor. When specifying the target, ensure that you append the suffix _editable-content to the ID. This configuration allows users to mention or tag others from the suggested list while editing text.

When a user types the @ symbol followed by a character, the Markdown Editor displays a list of suggestions. Users can select an item from the list by either clicking on it or typing the desired name.

Configuring Mention Properties

The Syncfusion Mention control provides several customizable properties to enhance the tagging experience:

  • allowSpaces - Allow to continue search action if user enter space after mention character while searching.
  • suggestionCount - Defines the maximum number of items displayed in the suggestion list.
  • itemTemplate - Customizes the appearance of items in the suggestion list.

Example: Implementing Mention in Markdown Editor

The following example demonstrates how to enable Mention support in the Markdown Editor.

@{
    var mentionData = new EditorMentionUser().GetUserData();
}
<ejs-richtexteditor id="defaultmarkdown" value="@ViewBag.value" height="250px" editorMode="Markdown"  created="created" placeholder="Enter your text here...">
    <e-richtexteditor-toolbarsettings items="@ViewBag.items"></e-richtexteditor-toolbarsettings>
</ejs-richtexteditor>
<ejs-mention id="editorMention" dataSource="@mentionData" allowSpaces="true" popupHeight="200px" popupWidth="250px" sortOrder="Ascending"
             target="#defaultmarkdown_editable-content" created="mentionCreated"
             itemTemplate="<div class='editor-mention-item-template'>
                    <div class='em-header'>
                        <div class='em-avatar' style='background-color: ${BgColor}; color: ${Color};'>
                            <div class='em-initial'>${Initial}</div>
                        </div>
                    </div>
                    <div class='em-content'>
                        <div class='em-name'>${Name}</div>
                        <div class='em-email'>${Email}</div>
                    </div>
                </div>"
             displayTemplate="[@@${Name}](mailto:${Email})">
    <e-mention-fields text="Name"></e-mention-fields>
</ejs-mention>

<script type="text/javascript">
    var rteObj, textArea, mdsource, mentionObj;
    function created() {
        rteObj = this;
        rteObj.formatter = new ej.richtexteditor.MarkdownFormatter({ listTags: { 'OL': '1., 2., 3.' } });
        rteObj.dataBind();
        textArea = rteObj.contentModule.getEditPanel();
        textArea.addEventListener('keyup', function (e) {
            markdownConversion();
        });
        mdsource = document.getElementById('preview-code');
        mdsource.addEventListener('click', function (e) {
            fullPreview();
            if (e.currentTarget.classList.contains('e-active')) {
                rteObj.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                    'UnorderedList', 'CreateLink', 'Image', 'Formats', 'Undo', 'Redo', 'CreateTable', 'SuperScript', 'SubScript']);
            }
            else {
                rteObj.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                    'UnorderedList', 'CreateLink', 'Image', 'Formats', 'Undo', 'Redo', 'CreateTable', 'SuperScript', 'SubScript']);
            }
        });
    }
    loadExternalFile();
    function loadExternalFile() {
        var script = document.createElement('script');
        script.src = 'https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js';
        document.getElementsByTagName('head')[0].appendChild(script);
    }
    function markdownConversion() {
        if (mdsource.classList.contains('e-active')) {
            var id = rteObj.getID() + 'html-preview';
            var htmlPreview = rteObj.element.querySelector('#' + id);
            htmlPreview.innerHTML = marked(rteObj.contentModule.getEditPanel().value);
        }
    }
    function mentionCreated() {
        mentionObj = this;
    }
    function fullPreview() {
        var id = rteObj.getID() + 'html-preview';
        var htmlPreview = rteObj.element.querySelector('#' + id);
        var previewTextArea = rteObj.element.querySelector('.e-rte-content');
        if (mdsource.classList.contains('e-active')) {
            mdsource.classList.remove('e-active');
            mdsource.parentElement.title = 'Preview';
            textArea.style.display = 'block';
            htmlPreview.style.display = 'none';
            previewTextArea.style.overflow = 'hidden';
        }
        else {
            mdsource.classList.add('e-active');
            if (!htmlPreview) {
                htmlPreview = ej.base.createElement('div', { className: 'e-content e-pre-source' });
                htmlPreview.id = id;
                textArea.parentNode.appendChild(htmlPreview);
                previewTextArea.style.overflow = 'auto';
            }
            if (previewTextArea.style.overflow === 'hidden') {
                previewTextArea.style.overflow = 'auto';
            }
            textArea.style.display = 'none';
            htmlPreview.style.display = 'block';
            htmlPreview.innerHTML = marked(rteObj.contentModule.getEditPanel().value);
            mdsource.parentElement.title = 'Code View';
        }
    }
</script>

<style>
    .editor-mention-item-template {
        width: 100%;
        height: 100%;
        display: flex;
        flex-direction: row;
        align-items: center;
    }

    .em-content {
        display: flex;
        flex-direction: column;
        justify-content: center;
    }

    .em-avatar {
        width: 32px;
        height: 32px;
        text-align: center;
        border-radius: 50%;
        font-size: 12px;
        font-weight: 500;
        text-indent: 0px;
        line-height: 13px;
        color: #fff;
        display: flex;
        align-items: center;
        justify-content: center;
    }

    .em-name {
        color: rgb(16, 24, 40);
        font-size: 14px;
        font-weight: 400;
        line-height: 14px;
        margin-bottom: 5px;
    }

    .em-email {
        color: gray;
        font-size: 12px;
        font-weight: 400;
        line-height: 14px;
    }

    #defaultmarkdown_editable-content_popup li {
        padding: 10px;
        height: 60px;
    }

    body[class*="-dark"] .em-name {
        color: #fff !important;
    }

    .e-richtexteditor textarea.e-content {
        float: left;
    }

    .e-richtexteditor .e-rte-content {
        overflow: hidden;
    }

    .e-icon-btn.e-active .e-md-preview::before {
        content: '\e350';
    }

    .e-icon-btn .e-md-preview::before {
        content: '\e345';
    }

    .bootstrap4 .e-icon-btn.e-active .e-md-preview::before {
        content: '\e790';
    }

    .bootstrap4 .e-icon-btn .e-md-preview::before {
        content: '\e787';
    }

    .fluent .e-icon-btn.e-active .e-md-preview::before,
    .fluent-dark .e-icon-btn.e-active .e-md-preview::before,
    .fluent2 .e-icon-btn.e-active .e-md-preview::before,
    .fluent2-dark .e-icon-btn.e-active .e-md-preview::before,
    .fluent2-highcontrast .e-icon-btn.e-active .e-md-preview::before,
    .tailwind .e-icon-btn.e-active .e-md-preview::before,
    .tailwind-dark .e-icon-btn.e-active .e-md-preview::before,
    .tailwind3 .e-icon-btn.e-active .e-md-preview::before,
    .tailwind3-dark .e-icon-btn.e-active .e-md-preview::before,
    .bootstrap5 .e-icon-btn.e-active .e-md-preview::before,
    .bootstrap5-dark .e-icon-btn.e-active .e-md-preview::before,
    .bootstrap5\.3 .e-icon-btn.e-active .e-md-preview::before,
    .bootstrap5\.3-dark .e-icon-btn.e-active .e-md-preview::before,
    .material3 .e-icon-btn.e-active .e-md-preview::before,
    .material3-dark .e-icon-btn.e-active .e-md-preview::before {
        content: '\e80e';
    }

    .tailwind .e-icon-btn .e-md-preview::before,
    .tailwind-dark .e-icon-btn .e-md-preview::before,
    .tailwind3 .e-icon-btn .e-md-preview::before,
    .tailwind3-dark .e-icon-btn .e-md-preview::before,
    .bootstrap5 .e-icon-btn .e-md-preview::before,
    .bootstrap5-dark .e-icon-btn .e-md-preview::before,
    .bootstrap5\.3 .e-icon-btn .e-md-preview::before,
    .bootstrap5\.3-dark .e-icon-btn .e-md-preview::before,
    .fluent .e-icon-btn .e-md-preview::before,
    .fluent-dark .e-icon-btn .e-md-preview::before,
    .fluent2 .e-icon-btn .e-md-preview::before,
    .fluent2-dark .e-icon-btn .e-md-preview::before,
    .fluent2-highcontrast .e-icon-btn .e-md-preview::before,
    .material3 .e-icon-btn .e-md-preview::before,
    .material3-dark .e-icon-btn .e-md-preview::before {
        content: '\e7de';
    }

</style>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace WebApplication1.Models
{
    public class EditorMentionUser {
        public string Name { get; set; }
        public string Initial { get; set; }
        public string Email { get; set; }
        public string Color { get; set; }
        public string BgColor { get; set; }
        public List<EditorMentionUser> GetUserData() 
        {
            List<EditorMentionUser> data = new List<EditorMentionUser>
            {
                new EditorMentionUser { Name = "Selma Rose", Initial = "SR", Email = "selma@gmail.com", Color = "#FAFDFF", BgColor = "#01579B" },
                new EditorMentionUser { Name = "Maria", Initial = "MA", Email = "maria@gmail.com", Color = "#004378", BgColor = "#ADDBFF" },
                new EditorMentionUser { Name = "Russo Kay", Initial = "RK", Email = "russo@gmail.com", Color = "#F9DEDC", BgColor = "#8C1D18" },
                new EditorMentionUser { Name = "Robert", Initial = "RO", Email = "robert@gmail.com", Color = "#FFD6F7", BgColor = "#37003A" },
                new EditorMentionUser { Name = "Camden Kate", Initial = "CK", Email = "camden@gmail.com", Color = "#FFFFFF", BgColor = "#464ECF" },
                new EditorMentionUser { Name = "Garth", Initial = "GA", Email = "garth@gmail.com", Color = "#FFFFFF", BgColor = "#008861" },
                new EditorMentionUser { Name = "Andrew James", Initial = "AJ", Email = "james@gmail.com", Color = "#FFFFFF", BgColor = "#53CA17" },
                new EditorMentionUser { Name = "Olivia", Initial = "OL", Email = "olivia@gmail.com", Color = "#FFFFFF", BgColor = "#8C1D18" },
                new EditorMentionUser { Name = "Sophia", Initial = "SO", Email = "sophia@gmail.com", Color = "#000000", BgColor = "#D0BCFF" },
                new EditorMentionUser { Name = "Margaret", Initial = "MA", Email = "margaret@gmail.com", Color = "#000000", BgColor = "#F2B8B5" },
                new EditorMentionUser { Name = "Ursula Ann", Initial = "UA", Email = "ursula@gmail.com", Color = "#000000", BgColor = "#47ACFB" },
                new EditorMentionUser { Name = "Laura Grace", Initial = "LG", Email = "laura@gmail.com", Color = "#000000", BgColor = "#FFE088" },
                new EditorMentionUser { Name = "Albert", Initial = "AL", Email = "albert@gmail.com", Color = "#FFFFFF", BgColor = "#00335B" },
                new EditorMentionUser { Name = "William", Initial = "WA", Email = "william@gmail.com", Color = "#FFFFFF", BgColor = "#163E02" }
            };

            return data;
        }
    }
}
public class HomeController : Controller
{

    public ActionResult Index()
    {
         object tools1 = new
            {
                tooltipText = "Preview",
                template = "<button id='preview-code' class='e-tbar-btn e-control e-btn e-icon-btn'>" +
                           "<span class='e-btn-icon e-md-preview e-icons'></span></button>"
            };
            
            ViewBag.items = new[]
            {
                "Bold", "Italic", "StrikeThrough", "|", "SuperScript",
                "SubScript", "Formats", "OrderedList", "UnorderedList" , "|", tools1 , "CreateLink", "Image", "CreateTable", "|", 
                "Undo", "Redo"
            };

            ViewBag.value = @"Hello [Albert](mailto:albert@gmail.com)\n\nWelcome to the mention integration with markdown editor demo. Type @ character and tag user from the suggestion list.";
            return View();
    }
}