Code Editor

TsgcHTMLComponent_CodeEditor: a code editor for web pages built on CodeMirror 6. It highlights SQL, JSON, JavaScript, HTML, CSS, XML, Markdown, Python and Pascal, folds blocks, finds and replaces, completes SQL with the tables and columns of your schema and marks JSON errors as you type. Its text posts with the form like a textarea, in Delphi, C++ Builder and .NET.

TsgcHTMLComponent_CodeEditor

Set the Language and put its HTML inside a form. The text lives in a <textarea> that the form posts like any other field, so the editor needs no code of its own and still works as a plain textarea without JavaScript. The optional OnChange event sends the text to the server while the user types.

Component class

TsgcHTMLComponent_CodeEditor, a code editor whose text is a posted form field

Renders

A CodeMirror 6 editor over a <textarea>. The library is embedded in the component resources and served by the engine as /codemirror.min.js, with no CDN

Languages

Delphi, C++ Builder, .NET

A SQL editor in a form, JSON checked on the server

SQLSchema gives the completion the tables and columns of your database. On the post, GetValueFromRequest reads the text of the editor and ValidateJSONValue checks the JSON before you store it.

uses
  sgcHTML_Component_CodeEditor;

// a SQL editor in a form
oSQL := TsgcHTMLComponent_CodeEditor.Create(Self);
oSQL.Name := 'query';
oSQL.Language := celSQL;
oSQL.SQLDialect := cesPostgreSQL;
oSQL.SQLSchema.Add('customers=id,name,email,country');
oSQL.SQLSchema.Add('orders=id,customer_id,total,created_at');
oSQL.Placeholder := 'SELECT ...';
oSQL.CSSHeight := '240px';
oSQL.Required := True;
sHtml := '<form method="post" action="/report">' + oSQL.HTML +
  '<button type="submit" class="btn btn-primary mt-2">Run</button></form>';

// a JSON settings editor that grows with the text
oSettings := TsgcHTMLComponent_CodeEditor.Create(Self);
oSettings.Name := 'settings';
oSettings.Language := celJSON;
oSettings.CSSHeight := 'auto';
oSettings.CSSMaxHeight := '400px';
oSettings.Value := LoadSettings;

// the post of the settings form
procedure TForm1.SaveSettingsPost(const aParams: TStrings; var aResponse: string);
var
  vJSON, vError: string;
begin
  vJSON := oSettings.GetValueFromRequest(aParams);
  if oSettings.ValidateJSONValue(vJSON, vError) then
  begin
    SaveSettings(vJSON);
    aResponse := '<div class="alert alert-success">Saved</div>';
  end
  else
    aResponse := '<div class="alert alert-danger">' + sgcHTMLEncode(vError) + '</div>';
end;
@* a SQL editor and a JSON editor in one form *@
<form method="post">
  <label for="query_input" class="form-label">Query</label>
  <sgc-code-editor name="query" language="sql" sql-dialect="postgresql"
                   sql-schema="customers=id,name,email;orders=id,customer_id,total"
                   value="@Model.Query" css-height="240px" required="true" />
  <sgc-code-editor name="settings" language="json" css-height="auto"
                   css-max-height="400px" value="@Model.Settings"
                   on-change="Model.SettingsChanged" />
  <button type="submit" class="btn btn-primary mt-2">Save</button>
</form>
using esegece.sgcWebSockets;

// a SQL editor in a form
var sql = new TsgcHTMLComponent_CodeEditor();
sql.Name = "query";
sql.Language = TsgcHTMLCodeEditorLanguage.celSQL;
sql.SQLDialect = TsgcHTMLCodeEditorSQLDialect.cesPostgreSQL;
sql.SQLSchema.Add("customers=id,name,email,country");
sql.SQLSchema.Add("orders=id,customer_id,total,created_at");
sql.CSSHeight = "240px";
sql.Required = true;

// a JSON settings editor that grows with the text
var settings = new TsgcHTMLComponent_CodeEditor();
settings.Name = "settings";
settings.Language = TsgcHTMLCodeEditorLanguage.celJSON;
settings.CSSHeight = "auto";
settings.CSSMaxHeight = "400px";
settings.Value = LoadSettings();

// the post of the settings form
string SaveSettingsPost(IReadOnlyList<string> fields)
{
    string json = settings.GetValueFromRequest(fields);
    if (settings.ValidateJSONValue(json, out string error))
    {
        SaveSettings(json);
        return "<div class=\"alert alert-success\">Saved</div>";
    }
    return "<div class=\"alert alert-danger\">" + WebUtility.HtmlEncode(error) + "</div>";
}

What your users get

The editor of a desktop IDE inside a web page, and a field your forms post with no code of their own.

Ten languages

Language selects SQL, JSON, JavaScript, HTML with its embedded CSS and JavaScript, CSS, XML, Markdown, Python, Pascal or plain text. Every language is highlighted, SQL adds completion and JSON adds a syntax check.

SQL completion and dialects

SQLDialect selects the keywords, types, functions and identifier quoting of Standard SQL, PostgreSQL, MySQL, Microsoft SQL Server (T-SQL) or SQLite. SQLSchema lists your tables and columns, and SQLSchemaGrid adds the columns of a Grid as one more table. Type a table name and a dot to see its columns, or press Ctrl+Space.

JSON syntax check

With ValidateJSON the editor marks JSON syntax errors while the user types, and the error list tells what is wrong. On the server, ValidateJSONValue checks the posted text and returns the error, so a broken settings file never reaches your store.

Find, replace and go to line

Ctrl+F opens the find and replace panel at the top of the editor, with match case, regular expression and whole word options, replace and replace all. F3 and Shift+F3 find the next and the previous match, and Ctrl+Alt+G goes to a line.

Folding and editing

Line numbers, a highlighted active line and a fold gutter, each one turned on or off with LineNumbers, HighlightActiveLine and FoldGutter. Ctrl+Shift+[ and Ctrl+Shift+] fold and unfold the block at the cursor, Tab indents by TabSize spaces, and Ctrl+Z and Ctrl+Y undo and redo. WordWrap wraps long lines.

Works in any form

The editor copies every change into its textarea and fires an input event, so a form posts the current text and form libraries see the change. A click on its label moves the focus into the editor. With Required the browser, and the validation of a Form, do not send the form while the editor is empty.

Light and dark

Theme cetAuto follows the data-bs-theme of the page, with the One Dark theme of CodeMirror when it is dark, and recolors at once when the theme switches. cetLight and cetDark fix the colors. CSSHeight sets a fixed height, or auto to grow with the text between CSSMinHeight and CSSMaxHeight.

Accessibility

The textarea and the editing area share the accessible name of AriaLabel, or Code editor from the locale, and report read only and required. Inside the editor Tab indents, so Esc and then Tab moves the focus out. On macOS Cmd takes the place of Ctrl.

Key properties, methods & events

The members you reach for most often.

Value and the posted field

Value is the text of the editor. The textarea is posted under FieldName, else the Name of the component, else code (GetFieldName). On the server GetValueFromRequest returns the posted text and LoadFromRequest sets Value from it. A form post sends the line breaks as CRLF, the rule of the browsers for a textarea.

OnChange

OnChange(Sender, aValue, aResponse) receives the text ChangeDelay ms (500 by default) after the user stops typing, through the component events of the HTMXEngine, or of your own route with ActionURL and DispatchComponentEvent. The browser posts only while the handler is assigned and the editor is not ReadOnly, and htmx swaps the HTML you return when its elements are marked hx-swap-oob="true".

JavaScript API

window.sgcHTMLCodeEditor offers get(id), setValue(id, text), focus(id) and scan(node). Editors in content that htmx swaps in are created, and editors that htmx removes are destroyed, with no code of your own.

One library per page

CodeMirror 6 is embedded in the component resources and served by the engine as /codemirror.min.js. The browser loads it once per page, only on pages that have an editor, however many editors they have. When it can not load, every editor of the page stays a plain textarea and the form still posts it. CodeMirror is released under the MIT License.

Localization

The find and replace panel, the go to line prompt, the fold markers, the completion list and the JSON errors take their texts from the locale of the library, in the 17 languages it ships.

Limits

OnChange posts the whole text through the server events endpoint, whose body limit is 64 KB. Use it for small texts, and read large ones from the form post. One component serves every user: read the posted text with GetValueFromRequest and do not change the component in OnChange.

ASP.NET Core

In a Razor view the <sgc-code-editor> Tag Helper renders the editor. The first render creates one component per engine and name, and every render sets its properties again from the attributes. name is required, and the Tag Helper has no attribute for SQLSchemaGrid: list the columns of the grid in sql-schema.

The demo

Demos\60.HTML\01.RunTime\30.CodeEditor is the sgc Admin Console, a server on port 8132: a SQL console with schema completion that runs queries on the server into a Grid, JSON settings validated on the server and applied live in every browser, and a read only snippet viewer. The design time, Lazarus and .NET versions mirror it.

Keep exploring

Try It OnlineSee it in the Code Editor demo, running live on the eSeGeCe demo server.
Online HelpFull API reference and usage guide for this component.
Rich Editor ComponentThe WYSIWYG editor for formatted text, posted with the form the same way.
All sgcHTML ComponentsBrowse the full feature matrix of 80+ components.
Download Free TrialThe 30-day trial ships the 60.HTML demo projects.
PricingSingle, Team and Site licenses with full source code.
Best value: All-AccessEvery eSeGeCe product, Premium Support included, from €1,059/year.
See All-Access pricing

Ready to Get Started?

Download the free trial and start building web UIs in Delphi, C++ Builder and .NET.