Search results

Markdown

When you format the word in Markdown format, you should add Markdown syntax to the word to indicate the words and phrases that looks different from each other.

RichTextEditor supports markdown editing when the editorMode set as markdown and using both keyboard interaction and toolbar action, you can apply the formatting to text

To use quick Markdown editing feature, inject MarkdownEditorService in the provider section of AppModule.

Supported Tools

The editor’s toolbar contains commands to format the markdown content. The toolbar consists of:

Tools Description
Lists Ordered and unordered list types.
Links A hyperlink can be inserted into the editor for quick access to related information.
Image Inserts and manages images.
Format Formats the sentence in different ways such as heading level, quotation, and code snippet.
Styles Allows you to apply inline styles to the selected content like bold, italic, and more.
Table A table can be insert into the editor.

Markdown to HTML

The RichTextEditor allows you to preview markdown changes immediately using preview. In this sample, the third-party library Marked is used to convert markdown into HTML content.

This sample demonstrates how to preview markdown changes in RichTextEditor. Type or edit the display text, and apply format to view the preview of markdown. The actionComplete event can be used to convert Markdown to HTML.

Source
Preview
app.component.ts
app.module.ts
main.ts
index.html
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
/**
 * RichTextEditor Markdown Preview demo
 */
import { Component, ViewChild } from '@angular/core';
import { addClass, removeClass, Browser } from '@syncfusion/ej2-base';
import { RichTextEditorComponent, ToolbarService, LinkService } from '@syncfusion/ej2-angular-richtexteditor';
import { ImageService, MarkdownEditorService } from '@syncfusion/ej2-angular-richtexteditor';
import { createElement, KeyboardEventArgs, isNullOrUndefined } from '@syncfusion/ej2-base';
import * as Marked from 'marked';
    @Component({
    selector: 'app-root',
    template: `<ejs-richtexteditor id='mdPreview' #mdPreview [toolbarSettings]='tools' [editorMode]='mode' (created)='onCreate()' (actionComplete)="actionComplete($event)">
        <ng-template #valueTemplate>
            In RichTextEditor , you click the toolbar buttons to format the words and the changes are visible immediately.
            Markdown is not like that. When you format the word in Markdown format, you need to
            add Markdown syntax to the word to indicate which words
            and phrases should look different from each other.
            RichTextEditor supports markdown editing when the editorMode set as **markdown** and using both *keyboard interaction* and *toolbar action*, you can apply the formatting to text.
            You can add our own custom formation syntax for the Markdown formation, [sample link](https://ej2.syncfusion.com/home/).
            The third-party library <b>Marked</b> is used in this sample to convert markdown into HTML content.
        </ng-template>
    </ejs-richtexteditor>`,
    providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService]
    })
export class AppComponent  {
        @ViewChild('mdPreview')
public rteObj: RichTextEditorComponent;
public textArea: HTMLTextAreaElement;
public mdsource: HTMLElement;
public mdSplit: HTMLElement;
public htmlPreview: HTMLElement;
public tools: object = {
    items: ['Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList', 'UnorderedList', '|', 'CreateLink', 'Image', '|',
        {
            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>'
        }, {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-view-side e-icons"></span></button>'
        }, 'FullScreen', '|', 'Undo', 'Redo']
};
public mode: string = 'Markdown';
public onCreate(): void {
    let script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/marked/marked.min.js';
    document.head.appendChild(script);
    this.textArea = this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement;
    this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
        this.markDownConversion();
    });
    this.mdsource = document.getElementById('preview-code');
    this.mdsource.addEventListener('click', (e: MouseEvent) => {
        this.fullPreview({ mode: true, type: 'preview' });
        if ((e.target as HTMLElement).parentElement.classList.contains('e-active')) {
            this.rteObj.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.add('e-overlay');
        } else {
            this.rteObj.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.remove('e-overlay');
        }
    });
    this.mdSplit = document.getElementById('MD_Preview');
    this.mdSplit.addEventListener('click', (e: MouseEvent) => {
        if (this.rteObj.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
        }
        this.mdsource.classList.remove('e-active');
        this.rteObj.showFullScreen();
    });
}
public actionComplete(e: any): void {
    if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
        this.fullPreview({ mode: true, type: '' });
    } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
        if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
            this.mdSplit.classList.remove('e-active');
            this.mdsource.classList.remove('e-active');
        }
        this.markDownConversion();
    }
}
public markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
        let id: string = this.rteObj.getID() + 'html-preview';
        let htmlPreview: HTMLElement = this.rteObj.element.querySelector('#' + id) as HTMLElement;
        debugger
        htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
public fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.rteObj.getID() + 'html-preview';
    this.htmlPreview = this.rteObj.element.querySelector('#' + id) as HTMLElement;
    if ((this.mdsource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
        this.mdsource.classList.remove('e-active');
        this.mdSplit.classList.remove('e-active');
        this.textArea.style.display = 'block';
        this.textArea.style.width = '100%';
        this.htmlPreview.style.display = 'none';
    } else {
        this.mdsource.classList.add('e-active');
        this.mdSplit.classList.add('e-active');
        if (!this.htmlPreview) {
            this.htmlPreview = createElement('div', { className: 'e-content' });
            this.htmlPreview.id = id;
            this.textArea.parentNode.appendChild(this.htmlPreview);
        }
        if (e.type === 'preview') {
            this.textArea.style.display = 'none';
            this.htmlPreview.classList.add('e-pre-source');
        } else {
            this.htmlPreview.classList.remove('e-pre-source');
            this.textArea.style.width = '50%';
        }
        this.htmlPreview.style.display = 'block';
        this.htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RichTextEditorAllModule } from '@syncfusion/ej2-angular-richtexteditor';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-angular-dropdowns';
import { AppComponent } from './app.component';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        ButtonModule,
        RichTextEditorAllModule
    ],
    declarations: [AppComponent, DropDownListComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion Angular RichTextEditor</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
     <link href="//cdn.syncfusion.com/ej2/ej2-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/material.css" rel="stylesheet" />
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.6.25/zone.min.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
    #loader {
        color: #008cff;
        font-family:  'Helvetica Neue','calibiri';
        font-size: 16px;
        height: 40px;
        left: 45%;
        position: absolute;
        top: 45%;
        width: 30%;
    }
     #mdPreview.e-richtexteditor textarea.e-content {
        float: left;
        border-right: 1px solid rgba(0, 0, 0, 0.12);
    }
    #mdPreview.e-richtexteditor .e-rte-content .e-content{
        min-height: 150px;
    }

    #mdPreview.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';
    }

    #mdPreview .e-rte-content .e-content.e-pre-source {
        width: 100%;
    }

    .highcontrast #mdPreview.e-richtexteditor textarea.e-content {
        border-right: 1px solid #fff;
    }
</style>
</head>

<body>
    <app-root>
        <div id='loader'>Loading....</div>
    </app-root>
</body>

</html>

Table

RichTextEditor allows to insert Markdown table in edit panel with 2 X 2 rows and columns along with the heading. To use table tool, add the CreateTable item in toolbar items.

Insert table

To insert the table in RichTextEditor’s content area, click the insert table icon in the toolbar option. Please refer the below sample and code snippets to add the table in Markdown editor

Source
Preview
app.component.ts
app.module.ts
main.ts
index.html
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
/**
 * RichTextEditor Markdown demo with table
 */
import { Component, ViewChild } from '@angular/core';
import { RichTextEditorComponent, ToolbarService, LinkService } from '@syncfusion/ej2-angular-richtexteditor';
import { ImageService, MarkdownEditorService } from '@syncfusion/ej2-angular-richtexteditor';
import { createElement, KeyboardEventArgs, isNullOrUndefined } from '@syncfusion/ej2-base';
import * as Marked from 'marked';
@Component({
selector: 'app-root',
template: `<ejs-richtexteditor id='mdPreview' #mdPreview [toolbarSettings]='tools' [editorMode]='mode' (created)='onCreate()'
            (actionComplete)="actionComplete($event)">
            <ng-template #valueTemplate>
                In RichTextEditor , you click the toolbar buttons to format the words and the changes are visible immediately.
                Markdown is not like that. When you format the word in Markdown format, you need to
                add Markdown syntax to the word to indicate which words
                and phrases should look different from each other.
                RichTextEditor supports markdown editing when the editorMode set as **markdown** and using
                both *keyboard interaction* and *toolbar action*,you can apply the formatting to text.
                You can add our own custom formation syntax for the Markdown formation, [sample link](https://ej2.syncfusion.com/home/).
                The third-party library <b>Marked</b> is used in this sample to convert markdown into HTML content.
            </ng-template>
           </ejs-richtexteditor>`,
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService]
})
export class AppComponent  {
      @ViewChild('mdPreview')
public rteObj: RichTextEditorComponent;
public textArea: HTMLTextAreaElement;
public mdsource: HTMLElement;
public mdSplit: HTMLElement;
public htmlPreview: HTMLElement;
public tools: object = {
    items: ['Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList',
            'UnorderedList', '|', 'CreateLink', 'Image', 'CreateTable', '|',
        {
            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>'
        }, {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-view-side e-icons"></span></button>'
        }, 'FullScreen', '|', 'Undo', 'Redo']
};
public mode: string = 'Markdown';
public onCreate(): void {
    let script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/marked/marked.min.js';
    document.head.appendChild(script);
    this.textArea = this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement;
    this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
        this.markDownConversion();
    });
    this.mdsource = document.getElementById('preview-code');
    this.mdsource.addEventListener('click', (e: MouseEvent) => {
        this.fullPreview({ mode: true, type: 'preview' });
        if ((e.target as HTMLElement).parentElement.classList.contains('e-active')) {
            this.rteObj.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image', 'CreateTable']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.add('e-overlay');
        } else {
            this.rteObj.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image', 'CreateTable']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.remove('e-overlay');
        }
    });
    this.mdSplit = document.getElementById('MD_Preview');
    this.mdSplit.addEventListener('click', (e: MouseEvent) => {
        if (this.rteObj.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
        }
        this.mdsource.classList.remove('e-active');
        this.rteObj.showFullScreen();
    });
}
public actionComplete(e: any): void {
    if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
        this.fullPreview({ mode: true, type: '' });
    } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
        if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
            this.mdSplit.classList.remove('e-active');
            this.mdsource.classList.remove('e-active');
        }
        this.markDownConversion();
    }
}
public markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
        let id: string = this.rteObj.getID() + 'html-preview';
        let htmlPreview: HTMLElement = this.rteObj.element.querySelector('#' + id) as HTMLElement;
        htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
public fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.rteObj.getID() + 'html-preview';
    this.htmlPreview = this.rteObj.element.querySelector('#' + id) as HTMLElement;
    if ((this.mdsource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
        this.mdsource.classList.remove('e-active');
        this.mdSplit.classList.remove('e-active');
        this.textArea.style.display = 'block';
        this.textArea.style.width = '100%';
        this.htmlPreview.style.display = 'none';
    } else {
        this.mdsource.classList.add('e-active');
        this.mdSplit.classList.add('e-active');
        if (!this.htmlPreview) {
            this.htmlPreview = createElement('div', { className: 'e-content' });
            this.htmlPreview.id = id;
            this.textArea.parentNode.appendChild(this.htmlPreview);
        }
        if (e.type === 'preview') {
            this.textArea.style.display = 'none';
            this.htmlPreview.classList.add('e-pre-source');
        } else {
            this.htmlPreview.classList.remove('e-pre-source');
            this.textArea.style.width = '50%';
        }
        this.htmlPreview.style.display = 'block';
        this.htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RichTextEditorAllModule } from '@syncfusion/ej2-angular-richtexteditor';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-angular-dropdowns';
import { AppComponent } from './app.component';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        ButtonModule,
        RichTextEditorAllModule
    ],
    declarations: [AppComponent, DropDownListComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion Angular RichTextEditor</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
     <link href="//cdn.syncfusion.com/ej2/ej2-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/material.css" rel="stylesheet" />
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.6.25/zone.min.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
    #loader {
        color: #008cff;
        font-family:  'Helvetica Neue','calibiri';
        font-size: 16px;
        height: 40px;
        left: 45%;
        position: absolute;
        top: 45%;
        width: 30%;
    }
     #mdPreview.e-richtexteditor textarea.e-content {
        float: left;
        border-right: 1px solid rgba(0, 0, 0, 0.12);
    }
    #mdPreview.e-richtexteditor .e-rte-content .e-content{
        min-height: 150px;
    }

    #mdPreview.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';
    }

    #mdPreview .e-rte-content .e-content.e-pre-source {
        width: 100%;
    }

    .highcontrast #mdPreview.e-richtexteditor textarea.e-content {
        border-right: 1px solid #fff;
    }
</style>
</head>

<body>
    <app-root>
        <div id='loader'>Loading....</div>
    </app-root>
</body>

</html>

Changing table constants

The Markdown table constants can be changed for the table heading and the column names.

Source
Preview
app.component.ts
app.module.ts
main.ts
index.html
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
/**
 * RichTextEditor changing table constants (markdown)
 */
import { Component, ViewChild } from '@angular/core';
import { RichTextEditorComponent, ToolbarService, LinkService } from '@syncfusion/ej2-angular-richtexteditor';
import { ImageService, MarkdownEditorService } from '@syncfusion/ej2-angular-richtexteditor';
import { createElement, KeyboardEventArgs, isNullOrUndefined } from '@syncfusion/ej2-base';
import { L10n } from '@syncfusion/ej2-base';
import * as Marked from 'marked';

L10n.load({
'en-US': {
    'richtexteditor': {
        'TableHeadingText': 'Header',
        'TableColText': 'Cell'
      }
  }
});
@Component({
selector: 'app-root',
template: `<ejs-richtexteditor id='mdPreview' #mdPreview [toolbarSettings]='tools' [editorMode]='mode'
(created)='onCreate()' (actionComplete)="actionComplete($event)">
    <ng-template #valueTemplate>
        In RichTextEditor , you click the toolbar buttons to format the words and the changes are visible immediately.
        Markdown is not like that. When you format the word in Markdown format, you need to
        add Markdown syntax to the word to indicate which words
        and phrases should look different from each other.
        RichTextEditor supports markdown editing when the editorMode set as **markdown** and using
        both *keyboard interaction* and *toolbar action*, you can apply the formatting to text.
        You can add our own custom formation syntax for the Markdown formation, [sample link](https://ej2.syncfusion.com/home/).
        The third-party library <b>Marked</b> is used in this sample to convert markdown into HTML content.
    </ng-template>
</ejs-richtexteditor>`,
providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService]
})
export class AppComponent  {
      @ViewChild('mdPreview')
public rteObj: RichTextEditorComponent;
public textArea: HTMLTextAreaElement;
public mdsource: HTMLElement;
public mdSplit: HTMLElement;
public htmlPreview: HTMLElement;
public tools: object = {
    items: ['Bold', 'Italic', 'StrikeThrough', '|', 'Formats', 'OrderedList', 'UnorderedList',
          '|', 'CreateLink', 'Image', 'CreateTable', '|',
        {
            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>'
        }, {
            tooltipText: 'Split Editor',
            template: '<button id="MD_Preview" class="e-tbar-btn e-control e-btn e-icon-btn">' +
            '<span class="e-btn-icon e-view-side e-icons"></span></button>'
        }, 'FullScreen', '|', 'Undo', 'Redo']
};
public mode: string = 'Markdown';
public onCreate(): void {
    let script = document.createElement('script');
    script.src = 'https://cdn.jsdelivr.net/npm/marked/marked.min.js';
    document.head.appendChild(script);
    this.textArea = this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement;
    this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
        this.markDownConversion();
    });
    this.mdsource = document.getElementById('preview-code');
    this.mdsource.addEventListener('click', (e: MouseEvent) => {
        this.fullPreview({ mode: true, type: 'preview' });
        if ((e.target as HTMLElement).parentElement.classList.contains('e-active')) {
            this.rteObj.disableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image', 'CreateTable']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.add('e-overlay');
        } else {
            this.rteObj.enableToolbarItem(['Bold', 'Italic', 'StrikeThrough', 'OrderedList',
                'UnorderedList', 'CreateLink', 'Image', 'CreateTable']);
            (e.target as HTMLElement).parentElement.parentElement.nextElementSibling.classList.remove('e-overlay');
        }
    });
    this.mdSplit = document.getElementById('MD_Preview');
    this.mdSplit.addEventListener('click', (e: MouseEvent) => {
        if (this.rteObj.element.classList.contains('e-rte-full-screen')) {
            this.fullPreview({ mode: true, type: '' });
        }
        this.mdsource.classList.remove('e-active');
        this.rteObj.showFullScreen();
    });
}
public actionComplete(e: any): void {
    if (e.targetItem === 'Maximize' && isNullOrUndefined(e.args)) {
        this.fullPreview({ mode: true, type: '' });
    } else if (!this.mdSplit.parentElement.classList.contains('e-overlay')) {
        if (e.targetItem === 'Minimize') {
            this.textArea.style.display = 'block';
            this.textArea.style.width = '100%';
            if (this.htmlPreview) { this.htmlPreview.style.display = 'none'; }
            this.mdSplit.classList.remove('e-active');
            this.mdsource.classList.remove('e-active');
        }
        this.markDownConversion();
    }
}
public markDownConversion(): void {
    if (this.mdSplit.classList.contains('e-active')) {
        let id: string = this.rteObj.getID() + 'html-preview';
        let htmlPreview: HTMLElement = this.rteObj.element.querySelector('#' + id) as HTMLElement;
        htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
public fullPreview(e: { [key: string]: string | boolean }): void {
    let id: string = this.rteObj.getID() + 'html-preview';
    this.htmlPreview = this.rteObj.element.querySelector('#' + id) as HTMLElement;
    if ((this.mdsource.classList.contains('e-active') || this.mdSplit.classList.contains('e-active')) && e.mode) {
        this.mdsource.classList.remove('e-active');
        this.mdSplit.classList.remove('e-active');
        this.textArea.style.display = 'block';
        this.textArea.style.width = '100%';
        this.htmlPreview.style.display = 'none';
    } else {
        this.mdsource.classList.add('e-active');
        this.mdSplit.classList.add('e-active');
        if (!this.htmlPreview) {
            this.htmlPreview = createElement('div', { className: 'e-content' });
            this.htmlPreview.id = id;
            this.textArea.parentNode.appendChild(this.htmlPreview);
        }
        if (e.type === 'preview') {
            this.textArea.style.display = 'none';
            this.htmlPreview.classList.add('e-pre-source');
        } else {
            this.htmlPreview.classList.remove('e-pre-source');
            this.textArea.style.width = '50%';
        }
        this.htmlPreview.style.display = 'block';
        this.htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
    }
}
}
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RichTextEditorAllModule } from '@syncfusion/ej2-angular-richtexteditor';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-angular-dropdowns';
import { AppComponent } from './app.component';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        ButtonModule,
        RichTextEditorAllModule
    ],
    declarations: [AppComponent, DropDownListComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion Angular RichTextEditor</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
     <link href="//cdn.syncfusion.com/ej2/ej2-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/material.css" rel="stylesheet" />
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.6.25/zone.min.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
    #loader {
        color: #008cff;
        font-family:  'Helvetica Neue','calibiri';
        font-size: 16px;
        height: 40px;
        left: 45%;
        position: absolute;
        top: 45%;
        width: 30%;
    }
     #mdPreview.e-richtexteditor textarea.e-content {
        float: left;
        border-right: 1px solid rgba(0, 0, 0, 0.12);
    }
    #mdPreview.e-richtexteditor .e-rte-content .e-content{
        min-height: 150px;
    }

    #mdPreview.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';
    }

    #mdPreview .e-rte-content .e-content.e-pre-source {
        width: 100%;
    }

    .highcontrast #mdPreview.e-richtexteditor textarea.e-content {
        border-right: 1px solid #fff;
    }
</style>
</head>

<body>
    <app-root>
        <div id='loader'>Loading....</div>
    </app-root>
</body>

</html>

Custom formation

The RichTextEditor allows you to customize the markdown syntax by overriding its default syntax. Configure the customized markdown syntax using the formatterproperty.

This sample demonstrates how to customize tags of markdown formatting.

For example, apply ‘+’ to Unordered list, apply ‘2’ to Ordered list, for bold, ‘_’, and for italic ‘’.

Source
Preview
app.component.ts
app.module.ts
main.ts
index.html
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
/**
 * RichTextEditor Markdown Preview Sample
 */
import { Component, ViewChild } from '@angular/core';
import { RichTextEditorComponent, MarkdownFormatter, ToolbarService } from '@syncfusion/ej2-angular-richtexteditor';
import { LinkService, ImageService, MarkdownEditorService } from '@syncfusion/ej2-angular-richtexteditor';
import { createElement, KeyboardEventArgs } from '@syncfusion/ej2-base';
import * as Marked from 'marked';
    @Component({
    selector: 'app-root',
    template: `<ejs-richtexteditor id='mdCustom' #mdCustom [toolbarSettings]='tools' [editorMode]='mode' [formatter]='formatter' (created)='onCreate()'>
        <ng-template #valueTemplate>
          The sample is configured with customized markdown syntax using the __formatter__ property.
          Type the content and click the toolbar item to view customized markdown syntax.
          For unordered list, you need to add a plus sign before the word (e.g., + list1).
          Or To make a phrase bold, you need to add two underscores before and after the phrase (e.g., __this text is bold__).
        </ng-template>
    </ejs-richtexteditor>`,
    providers: [ToolbarService, LinkService, ImageService, MarkdownEditorService]
    })
    export class AppComponent  {
    @ViewChild('mdCustom')
    public rteObj: RichTextEditorComponent;
    public textArea: HTMLTextAreaElement;
    public mdsource: HTMLElement;
    public tools: object = {
        items:  ['Bold', 'Italic', 'StrikeThrough', '|',
        'Formats', 'OrderedList', 'UnorderedList', '|',
        'CreateLink', 'Image', '|',
        {
            tooltipText: 'Preview',
            template: '<button id="preview-code" class="e-tbar-btn e-control e-btn e-icon-btn">' +
                '<span class="e-btn-icon e-icons e-md-preview"></span></button>'
        }, 'Undo', 'Redo']
    };
    public mode: string = 'Markdown';
     public formatter: MarkdownFormatter = new MarkdownFormatter({
        listTags: { 'OL': '2. ', 'UL': '+ ' },
        formatTags: {
            'Blockquote': '> '
        },
        selectionTags: {'Bold': '__',  'Italic': '_'}

    });
    public onCreate(): void {
        this.textArea = this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement;
        this.textArea.addEventListener('keyup', (e: KeyboardEventArgs) => {
            this.markDownConversion();
        });
        this.mdsource = document.getElementById('preview-code');
        this.mdsource.addEventListener('click', (e: MouseEvent) => {
            this.fullPreview();
        });
    }
    public markDownConversion(): void {
        if (this.mdsource.classList.contains('e-active')) {
            let id: string = this.rteObj.getID() + 'html-view';
            let htmlPreview: Element = this.rteObj.element.querySelector('#' + id);
            htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
        }
    }
    public fullPreview(): void {
        let id: string = this.rteObj.getID() + 'html-preview';
        let htmlPreview: HTMLElement = this.rteObj.element.querySelector('#' + id) as HTMLElement;
        if (this.mdsource.classList.contains('e-active')) {
            this.mdsource.classList.remove('e-active');
            this.textArea.style.display = 'block';
            htmlPreview.style.display = 'none';
        } else {
            this.mdsource.classList.add('e-active');
            if (!htmlPreview) {
                htmlPreview = createElement('div', { className: 'e-content e-pre-source' });
                htmlPreview.id = id;
                this.textArea.parentNode.appendChild(htmlPreview);
            }
            this.textArea.style.display = 'none';
            htmlPreview.style.display = 'block';
            htmlPreview.innerHTML = Marked((this.rteObj.contentModule.getEditPanel() as HTMLTextAreaElement).value);
            this.mdsource.parentElement.title = 'Code View';
        }
    }
    }
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RichTextEditorAllModule } from '@syncfusion/ej2-angular-richtexteditor';
import { ButtonModule } from '@syncfusion/ej2-angular-buttons';
import { DropDownListComponent } from '@syncfusion/ej2-angular-dropdowns';
import { AppComponent } from './app.component';

/**
 * Module
 */
@NgModule({
    imports: [
        BrowserModule,
        ButtonModule,
        RichTextEditorAllModule
    ],
    declarations: [AppComponent, DropDownListComponent],
    bootstrap: [AppComponent]
})
export class AppModule { }
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppModule } from './app.module';

enableProdMode();
platformBrowserDynamic().bootstrapModule(AppModule);
<!DOCTYPE html>
<html lang="en">

<head>
    <title>Syncfusion Angular RichTextEditor</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
     <link href="//cdn.syncfusion.com/ej2/ej2-richtexteditor/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-navigations/styles/material.css" rel="stylesheet" />
    <script src="https://unpkg.com/core-js/client/shim.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.6.25/zone.min.js"></script>
    <script src="https://unpkg.com/reflect-metadata@0.1.3"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/0.3.19/marked.js" type="text/javascript"></script>
    <script src="systemjs.config.js"></script>
    <style>
    #loader {
        color: #008cff;
        font-family:  'Helvetica Neue','calibiri';
        font-size: 16px;
        height: 40px;
        left: 45%;
        position: absolute;
        top: 45%;
        width: 30%;
    }
     #mdPreview.e-richtexteditor textarea.e-content {
        float: left;
        border-right: 1px solid rgba(0, 0, 0, 0.12);
    }
    #mdPreview.e-richtexteditor .e-rte-content .e-content{
        min-height: 150px;
    }

    #mdPreview.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';
    }

    #mdPreview .e-rte-content .e-content.e-pre-source {
        width: 100%;
    }

    .highcontrast #mdPreview.e-richtexteditor textarea.e-content {
        border-right: 1px solid #fff;
    }
</style>
</head>

<body>
    <app-root>
        <div id='loader'>Loading....</div>
    </app-root>
</body>

</html>