Skip to main content

LgHtmlEditor

LgHtmlEditor is an HTML input field based on Jodit. It inherits from LgInputBase<string>: it therefore supports @bind-Value binding, validation within an LgEditForm, policies, read-only mode, reset button, tooltips, and ARIA attributes.

<LgHtmlEditor Label="Content"
Height="200px"
@bind-Value="Model.HtmlTextContent" />
  • Namespace : Lagoon.UI.Components
  • Inherits from : LgInputBase<string> → LgAriaComponentBase → LgComponentBase
  • Interfaces : ILgComponentPolicies, IInputBusy, ILgFocusableComponent
  • NuGet Package : Lagoon.UI
Rich editor and form field

Like other components derived from LgInputBase<TValue>, LgHtmlEditor must be bound with Value, ValueChanged, or @bind-Value. In an LgEditForm, ValueExpression is automatically provided by @bind-Value and enables field validation.

Usage​

Demonstration​

Try this component in the Lagoon showcase.

In a form​

LgHtmlEditor is an LgInputBase<string> field: use @bind-Value in an LgEditForm to benefit from validation, value tracking, and Disabled / ReadOnly states.

ArticleEditPage.razor
@inherits LgPage

<LgEditForm Model="_vm" OnValidSubmit="SaveAsync">
<LgHtmlEditor CssClass="col-12"
Label="#ArticleContent"
Placeholder="#ArticleContentPlaceholder"
Height="240px"
MinHeight="200"
AllowResizeX="true"
AllowResizeY="true"
Required="true"
@bind-Value="_vm.HtmlTextContent" />

<LgButton Text="#Save" IconName="@IconNames.Save" Kind="ButtonKind.Primary" IsSubmit="true" />
</LgEditForm>
ArticleEditPage.razor.cs
public partial class ArticleEditPage : LgPage
{
// Model edited by the form; HTML content is updated by @bind-Value.
private ArticleVm _vm = new();

// Saves the HTML content validated by LgEditForm.
private Task SaveAsync(EditContext editContext)
{
ShowSuccess("#ArticleSaved");
return Task.CompletedTask;
}

private sealed class ArticleVm
{
public string HtmlTextContent { get; set; } = string.Empty;
}
}

Configure the Jodit toolbar​

Buttons limits the visible actions in the Jodit toolbar. FontSizeList, FontFamilyList, and DefaultFontSizePoints customize the typography lists. The Jodit AI assistant (the "AI Commands" and "AI Assistant" buttons) is disabled by Lagoon.

ArticleEditPage.razor
@inherits LgPage

<LgHtmlEditor Label="#ArticleContent"
Height="220px"
Buttons="_editorButtons"
FontSizeList="_fontSizes"
FontFamilyList="_fontFamilies"
DefaultFontSizePoints="pt"
@bind-Value="_vm.HtmlTextContent" />
ArticleEditPage.razor.cs
public partial class ArticleEditPage : LgPage
{
// Buttons displayed in the Jodit toolbar to simplify the editor on this page.
private readonly List<string> _editorButtons = new()
{
"bold",
"italic",
"underline",
"ul",
"ol",
"link",
"source"
};

// Font sizes offered in the size list to limit the values allowed by the project.
private readonly string[] _fontSizes = new[] { "10", "12", "14", "18", "24" };

// Available fonts in the editor; the key is the CSS value, the value is the displayed label.
private readonly Dictionary<string, string> _fontFamilies = new()
{
{ "Arial,Helvetica,sans-serif", "Arial" },
{ "Georgia,serif", "Georgia" },
{ "Verdana,Geneva,sans-serif", "Verdana" }
};
}

Adapt the editing mode​

Inline, Toolbar, TextIcons, Spellcheck, Language, and Style are passed to Jodit during initialization.

ArticleEditPage.razor
@inherits LgPage

<LgHtmlEditor Label="#InlineContent"
Inline="true"
Toolbar="false"
TextIcons="true"
Spellcheck="false"
Language="fr"
Style="_editorStyle"
@bind-Value="_vm.HtmlTextContent" />
ArticleEditPage.razor.cs
public partial class ArticleEditPage : LgPage
{
// Styles applied to the Jodit container, useful for adapting the editor to a compact area.
private readonly Dictionary<string, string> _editorStyle = new()
{
{ "max-width", "640px" },
{ "border", "1px solid var(--secondary)" }
};
}

Intercept input, change, and paste​

OnInput is called during input, OnChange after value validation (often on focus loss), and OnPasteAsync before pasted or drag-and-dropped content from outside the editor is inserted.

ArticleEditPage.razor
@inherits LgPage

<LgHtmlEditor Label="#ArticleContent"
@bind-Value="_vm.HtmlTextContent"
OnInput="OnInputAsync"
OnChange="OnChangeAsync"
OnPasteAsync="OnPasteAsync"
AskBeforePasteFromWord="true"
AskBeforePasteHTML="true"
ShowInsertAsHtml="true" />
ArticleEditPage.razor.cs
public partial class ArticleEditPage : LgPage
{
// Updates a preview or counter during input without waiting for focus loss.
private Task OnInputAsync(ChangeEventArgs args)
{
return Task.CompletedTask;
}

// Reacts after Jodit validates the value, for example to trigger a deferred save.
private Task OnChangeAsync(ChangeEventArgs args)
{
return Task.CompletedTask;
}

// Cleans pasted content before insertion in the editor to avoid unwanted tags.
private Task OnPasteAsync(HtmlEditorPasteEventArgs args)
{
args.Text = StripHtml(args.GetContent());
args.UseHtml = false;
args.AskBeforePasteHTML = false;
return Task.CompletedTask;
}

// Removes HTML tags when the page requires pasting as plain text.
private static string StripHtml(string content)
{
return Regex.Replace(content ?? string.Empty, "<.*?>", string.Empty);
}
}

Cancel a change before assignment​

OnChangingAsync is called by the input base before applying a new value. Set Cancel = true to reject the change.

ArticleEditPage.razor
@inherits LgPage

<LgHtmlEditor Label="#ArticleContent"
ConfirmationMessage="#ConfirmHtmlChange"
OnChangingAsync="OnChangingAsync"
@bind-Value="_vm.HtmlTextContent" />
ArticleEditPage.razor.cs
public partial class ArticleEditPage : LgPage
{
// Blocks a value containing a script to leave the previous content in the editor.
private Task OnChangingAsync(ChangingEventArgs<string> args)
{
if (args.NewValue?.Contains("<script", StringComparison.OrdinalIgnoreCase) == true)
{
args.Cancel = true;
ShowError("#HtmlContentRejected");
}
return Task.CompletedTask;
}
}

Display content in read-only mode​

When ReadOnly="true", the component does not load Jodit and renders the HTML in a read-only display.

ArticleDetailsPage.razor
@inherits LgPage

<LgHtmlEditor Label="#ArticleContent"
ReadOnly="true"
@bind-Value="_vm.HtmlTextContent" />

Sanitize content server-side​

Jodit cleans HTML in the browser, but this cleaning can be bypassed (direct API call, editor vulnerability). Before displaying to other users content entered with LgHtmlEditor (including in read-only mode, which renders the HTML as-is), sanitize it server-side with the LgHtmlSanitizer service, for example on save.

ArticleEditPage.razor
@inherits LgPage

<LgEditForm Model="_vm" OnValidSubmit="SaveAsync">
<LgHtmlEditor Label="#ArticleContent" @bind-Value="_vm.HtmlTextContent" />
<LgButton Text="#Save" IconName="@IconNames.Save" Kind="ButtonKind.Primary" IsSubmit="true" />
</LgEditForm>
ArticleController.cs (Server project)
public class ArticleController : LgControllerBase
{
private readonly LgHtmlSanitizer _htmlSanitizer;

public ArticleController(LgHtmlSanitizer htmlSanitizer)
{
_htmlSanitizer = htmlSanitizer;
}

[HttpPost]
public async Task<IActionResult> SaveAsync(ArticleDto article)
{
try
{
// Removes scripts, event handlers, javascript: URLs, and forms
article.HtmlTextContent = _htmlSanitizer.Sanitize(article.HtmlTextContent);
// ...
return Ok();
}
catch (Exception ex)
{
return Problem(ex);
}
}
}

Terms of use edited with LgHtmlEditor are automatically sanitized by Lagoon (see Terms of use).

Properties​

All component [Parameter] properties, including inherited ones.

NameTypeDefaultDeclared inDescription
AllowResizeXboolfalseLgHtmlEditorAllows horizontal resizing of the Jodit editor.
AllowResizeYboolfalseLgHtmlEditorAllows vertical resizing of the Jodit editor.
AskBeforePasteFromWordbooltrueLgHtmlEditorDisplays the Jodit dialog when pasting from Microsoft Word.
AskBeforePasteHTMLbooltrueLgHtmlEditorDisplays the Jodit dialog when pasting HTML content.
ButtonsList<string>nullLgHtmlEditorList of buttons displayed in the toolbar for large editor widths.
DefaultFontSizePointsstring"px"LgHtmlEditorFont size unit used by default; the source expects px or pt.
FontFamilyListDictionary<string, string>default dictionaryLgHtmlEditorFonts available in the Jodit list (Arial, Helvetica, Georgia, Impact, Tahoma, Times New Roman, Verdana).
FontSizeListstring[]new[] { "8", ..., "96" }LgHtmlEditorFont sizes available in the editor.
HeightstringnullLgHtmlEditorCSS height of the editor; enables the resize handle according to Jodit configuration.
InlineboolfalseLgHtmlEditorEnables Jodit's inline editing mode.
LanguagestringnullLgHtmlEditorForced editor language. If null or empty, the current culture (TwoLetterISOLanguageName) is used.
MinHeightint200LgHtmlEditorMinimum editor height, in pixels.
OnChangingAsyncFunc<ChangingEventArgs<string>, Task>nullLgHtmlEditorCallback called before applying a new value; can cancel the change.
OnInputEventCallback<ChangeEventArgs>—LgHtmlEditorCallback called on input, with the current HTML content in ChangeEventArgs.Value.
OnPasteAsyncFunc<HtmlEditorPasteEventArgs, Task>nullLgHtmlEditorCallback called before paste; allows reading or replacing the content to be inserted.
Placeholderstringstring.EmptyLgHtmlEditorPlaceholder text of the editor; translated with CheckTranslate().
ShowInsertAsHtmlboolfalseLgHtmlEditorDisplays the "Insert as HTML" option in HTML paste selection.
SpellcheckbooltrueLgHtmlEditorEnables the browser's spell and grammar checking.
StyleDictionary<string, string>nullLgHtmlEditorStyles applied to the main Jodit container, not to the edited HTML content.
TextIconsboolfalseLgHtmlEditorReplaces the editor's SVG icons with text.
ToolbarbooltrueLgHtmlEditorShows or hides the Jodit toolbar.
AdditionalAttributesIReadOnlyDictionary<string, object>nullLgInputBase<TValue>Additional attributes applied to the rendered container (captures unmapped values).
AutoFocusboolfalseLgInputBase<TValue>Gives focus to the field on first render.
ConfirmationMessagestringnullLgInputBase<TValue>Confirmation message displayed before applying a new value.
ContainerIInputContainer<string>nullLgInputBase<TValue>Internal parameter for integration with an input container, particularly a LgGridView cell.
CssClassstringnullLgInputBase<TValue>Additional CSS classes applied to the form-group-htmleditor container.
DisabledboolfalseLgInputBase<TValue>Disables the editor.
DisplayNamestringnullLgInputBase<TValue>Display name of the field, used in validation messages.
HideValidationMessageboolfalseLgInputBase<TValue>Hides inline validation messages for this field.
LabelstringnullLgInputBase<TValue>Label associated with the field.
LabelContentRenderFragmentnullLgInputBase<TValue>Customized label content.
OnChangeEventCallback<ChangeEventArgs>—LgInputBase<TValue>Callback called after applying a new value; ChangeEventArgs.Value contains the HTML.
OnResetEventCallback<ChangeEventArgs>—LgInputBase<TValue>Callback triggered after clicking the inherited reset button.
PolicyEditstringnullLgInputBase<TValue>Policy required to edit the field.
PolicyVisiblestringnullLgInputBase<TValue>Policy required to display the field.
ReadOnlyboolfalseLgInputBase<TValue>Displays content in read-only mode; the component then renders a span with the HTML.
Requiredbool?nullLgInputBase<TValue>Indicates whether the field is required. If null, the value is inferred from the model's [Required] attribute.
ResetButtonbool?nullLgInputBase<TValue>Displays the reset button. If null, the application configuration decides.
ResetTextstringnullLgInputBase<TValue>Text of the reset button. If null, the application configuration is used.
ResetTextAriaLabelstringnullLgInputBase<TValue>ARIA label of the reset button. If null, the application configuration is used.
TooltipstringnullLgInputBase<TValue>Tooltip applied to the field.
TooltipIsHtmlboolfalseLgInputBase<TValue>Indicates whether the tooltip contains HTML.
ValuestringnullLgInputBase<TValue>HTML value bound to the component.
ValueChangedEventCallback<string>—LgInputBase<TValue>Callback for updating the bound value (@bind-Value).
ValueExpressionExpression<Func<string>>nullLgInputBase<TValue>Expression identifying the bound field for the EditContext and validation.
AriaLabelstringnullLgAriaComponentBaseValue of the aria-label attribute.
AriaLabelledBystringnullLgAriaComponentBaseValue of the aria-labelledby attribute.
Cascading parameters

LgHtmlEditor consumes cascading parameters inherited from LgInputBase<string>: EditContext (parent form), LgEditFormConfiguration, ParentAuthorizeView, and InputBusyReference. They are automatically provided by ancestor components and are used for validation, policies, and restoring a pending value.

Events​

EventTypeDescription
OnChangeEventCallback<ChangeEventArgs>Triggered after validated change of the HTML value, typically on focus loss.
OnChangingAsyncFunc<ChangingEventArgs<string>, Task>Triggered before applying a new value; Cancel = true cancels the change.
OnInputEventCallback<ChangeEventArgs>Triggered during input via the JavaScript input callback.
OnPasteAsyncFunc<HtmlEditorPasteEventArgs, Task>Triggered before paste; allows choosing Text, Html, and UseHtml.
OnResetEventCallback<ChangeEventArgs>Triggered when the inherited reset button resets the value to default.
ValueChangedEventCallback<string>Triggered by the @bind-Value binding when the HTML value changes.

Accessibility​

  • Use Label, LabelContent, AriaLabel, or AriaLabelledBy to name the editor field.
  • Validation attributes (aria-invalid, aria-describedby) are automatically added by LgInputBase<string> when the EditContext contains errors.
  • Required adds aria-required, and ReadOnly adds aria-readonly via inherited mechanisms.
  • In read-only mode, HTML content is rendered as markup; ensure that the stored HTML remains semantic and accessible, and that it has been sanitized server-side.
  • LgButton — action component used with forms that host the editor.
  • LgLabelAction — display of a value with contextual action, useful to complement edited content.