Markdown Rich Text Editor
Double-click a value to edit. Apply or Ctrl/Cmd+Enter saves the draft. Cancel, Escape or outside dismissal discards it. Read-only cells cannot open or commit an editor.
Source code
<template>
<p>Double-click a value to edit. Apply saves; Cancel discards the draft.</p>
<RevoGrid
:source="source"
:columns="columns"
:plugins="plugins"
:theme="isDark ? 'darkMaterial' : 'material'"
style="height: 340px"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { currentThemeVue } from '../composables/useRandomData';
import RevoGrid from '@revolist/vue3-datagrid';
import { editorColumns, editorRows } from './editor-data';
const { isDark } = currentThemeVue();
const source = ref(editorRows());
const columns = editorColumns();
const plugins = [];
</script>
import { currentTheme } from '../composables/useRandomData';
import { defineCustomElements } from '@revolist/revogrid/loader';
import { editorColumns, editorRows } from './editor-data';
defineCustomElements();
export function load(parentSelector: string, rows = editorRows()) {
const grid = document.createElement('revo-grid');
grid.theme = currentTheme().isDark() ? 'darkMaterial' : 'material';
grid.style.height = '340px';
grid.columns = editorColumns();
document.querySelector(parentSelector)?.append(grid);
grid.source = rows;
return () => grid.remove();
}
import { currentTheme } from '../composables/useRandomData';
import { useMemo } from 'react';
import { RevoGrid } from '@revolist/react-datagrid';
import { editorColumns, editorRows } from './editor-data';
export default function EditorRichText({ rows }: { rows?: any[] }) {
const columns = useMemo(editorColumns, []);
const fallback = useMemo(editorRows, []);
const plugins = useMemo(() => [], []);
return (
<>
<p>
Double-click a value to edit. Apply saves; Cancel discards the draft.
</p>
<RevoGrid
source={rows?.length ? rows : fallback}
columns={columns}
plugins={plugins}
theme={currentTheme().isDark() ? 'darkMaterial' : 'material'}
style={{ height: '340px' }}
/>
</>
);
}
import { currentTheme } from '../composables/useRandomData';
import { Component, ViewEncapsulation } from '@angular/core';
import { RevoGrid } from '@revolist/angular-datagrid';
import { editorColumns, editorRows } from './editor-data';
@Component({
selector: 'editor-rich-text-grid',
standalone: true,
imports: [RevoGrid],
encapsulation: ViewEncapsulation.None,
template: `<p>
Double-click a value to edit. Apply saves; Cancel discards the draft.
</p>
<revo-grid
[source]="source"
[columns]="columns"
[plugins]="plugins"
[theme]="theme"
style="height:340px"
></revo-grid>`,
})
export class EditorRichTextGridComponent {
theme = currentTheme().isDark() ? 'darkMaterial' : 'material';
source = editorRows();
columns = editorColumns();
plugins = [];
}
import type { ColumnRegular } from '@revolist/revogrid';
import {
RichTextEditor,
markdownRenderer,
} from '@revolist/revogrid-pro/editors/rich-text';
import '@revolist/revogrid-pro/editors/rich-text.css';
export const editorRows = () => [
{
name: 'Planning',
value:
'# Planning\n\nReview **scope** and [requirements](https://rv-grid.com).',
},
{
name: 'Checklist',
value: '- Build shared controls\n- Add regression coverage',
},
{
name: 'Source-only content',
value: '| Field | Value |\n| --- | --- |\n| Status | Planned |',
},
];
export const editorColumns = (): ColumnRegular[] => [
{ prop: 'name', name: 'Task', size: 210, readonly: true },
{
prop: 'value',
name: 'Markdown notes · Visual / source',
size: 620,
editor: RichTextEditor,
cellTemplate: markdownRenderer,
richText: { maxLength: 50000 },
},
];
Import RichTextEditor from the optional @revolist/revogrid-pro/editors/rich-text entry and its editors/rich-text.css stylesheet. Lexical stays outside the base Pro runtime bundle.
Use cellTemplate: markdownRenderer from that same optional entry to render saved Markdown with RevoGrid’s native Stencil h() renderer. ColumnRichText includes it by default. Rendering uses the same minimal formatting set as the editor; unsupported content displays as literal source. No HTML is injected, unsafe links stay plain text, and cell content inherits the grid’s text color and size. The compact toolbar groups inline formatting, headings, lists/blocks and links using shared toggle buttons and Font Awesome SVG icons. Active controls follow the cursor’s formatting; accessible labels and tooltips identify every action.
Visual and Markdown source modes share one draft and store Markdown strings. Supported formatting includes paragraphs, headings, bold, italic, strikethrough, lists, blockquotes, links, inline code and fenced code blocks. Untouched Markdown is saved byte-for-byte. Enter inserts a newline; Ctrl/Cmd+Enter applies one grid edit. Local editing undo stays within the popup.
Images, tables, embeds, raw HTML, reference links, task lists, highlights and unsupported extensions remain intact in source mode. Unsupported content cannot silently transition into Visual mode. Raw HTML is treated as literal source and never injected into previews. Link protocols are validated; rich clipboard input is normalized to plain text. Configure richText.required, maxLength, localized text and action labels.
TextAreaEditor remains a plain-text multiline editor.
Use richText.text to translate mode names, popup and toolbar labels, link input, validation messages and unsupported-content categories. Formatting keys include bold, italic, strike, code, heading1, heading2, bullets, numberedList, quote and codeBlock; formatting labels the toolbar, and inlineFormatting, headings, structure and links label its groups. Partial richText.actions translates Apply, Cancel and Clear. Markdown syntax and stored strings remain unchanged by the interface locale.