|
| 1 | +--- |
| 2 | +title: Editor Focus Event |
| 3 | +description: Learn how to subscribe to the Editor focus event. |
| 4 | +type: how-to |
| 5 | +page_title: How to Handle the Editor Focus Event |
| 6 | +slug: editor-kb-focus-event |
| 7 | +tags: telerik, blazor, editor, events |
| 8 | +ticketid: 1695979 |
| 9 | +res_type: kb |
| 10 | +--- |
| 11 | + |
| 12 | +## Environment |
| 13 | + |
| 14 | +<table> |
| 15 | + <tbody> |
| 16 | + <tr> |
| 17 | + <td>Product</td> |
| 18 | + <td>Editor for Blazor</td> |
| 19 | + </tr> |
| 20 | + </tbody> |
| 21 | +</table> |
| 22 | + |
| 23 | +## Description |
| 24 | + |
| 25 | +This KB article answers the following questions: |
| 26 | + |
| 27 | +* How to detect when the user focuses the Editor content? |
| 28 | +* How to handle the Editor focus event? |
| 29 | +* Is it possible to do a Blazor action on Editor OnFocus? |
| 30 | + |
| 31 | +## Solution |
| 32 | + |
| 33 | +The required approach depends on the [Editor `EditMode`](slug:editor-edit-modes-overview), due to the different Editor HTML rendering: |
| 34 | + |
| 35 | +* [Using `Div` edit mode](#div-editmode) |
| 36 | +* [Using `Iframe` edit mode](#iframe-editmode) |
| 37 | + |
| 38 | +### `Div` EditMode |
| 39 | + |
| 40 | +1. Learn how to [call JavaScript code from C# code](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet). |
| 41 | +1. Wrap the Editor in a container with an `@onfocusin` event. |
| 42 | +1. Use JavaScript to check if the Editor content `<div class="k-content ProseMirror">` is focused. |
| 43 | + |
| 44 | +>caption Detect Editor focus when using Div EditMode |
| 45 | +
|
| 46 | +````RAZOR |
| 47 | +@using Telerik.Blazor.Components.Editor |
| 48 | +
|
| 49 | +@inject IJSRuntime js |
| 50 | +
|
| 51 | +<div @onfocusin="@OnDivEditorFocus"> |
| 52 | + <TelerikEditor @bind-Value="@EditorValue" |
| 53 | + Tools="@EditorToolSets.All" |
| 54 | + EditMode="@EditorEditMode.Div" |
| 55 | + Height="300px"> |
| 56 | + </TelerikEditor> |
| 57 | +</div> |
| 58 | +
|
| 59 | +@* Move JavaScript code to a separate JS file *@ |
| 60 | +<script suppress-error="BL9992"> |
| 61 | + function isEditorDivFocused() { |
| 62 | + return document.activeElement && |
| 63 | + document.activeElement.classList.contains("k-content") && |
| 64 | + document.activeElement.classList.contains("ProseMirror"); |
| 65 | + } |
| 66 | +
|
| 67 | +</script> |
| 68 | +
|
| 69 | +@code { |
| 70 | + #nullable enable |
| 71 | +
|
| 72 | + private string EditorValue { get; set; } = @"<p>foo 1</p><p>bar 1</p>"; |
| 73 | +
|
| 74 | + private async Task OnDivEditorFocus() |
| 75 | + { |
| 76 | + bool isEditorContentFocused = await js.InvokeAsync<bool>("isEditorDivFocused"); |
| 77 | +
|
| 78 | + if (isEditorContentFocused) |
| 79 | + { |
| 80 | + EditorValue = $"<p>Editor content DIV was focused at {DateTime.Now.ToLongTimeString()}.</p>"; |
| 81 | + } |
| 82 | + } |
| 83 | +} |
| 84 | +```` |
| 85 | + |
| 86 | +### `Iframe` EditMode |
| 87 | + |
| 88 | +1. Learn how to [call C# code from JavaScript code](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-dotnet-from-javascript) and [vice-versa](https://learn.microsoft.com/en-us/aspnet/core/blazor/javascript-interoperability/call-javascript-from-dotnet). |
| 89 | +1. Use the first firing of `OnAfterRenderAsync` to: |
| 90 | + 1. Obtain the `<body>` element inside the Editor content `iframe`. |
| 91 | + 1. [Subscribe](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) to the `focusin` event to the `iframe` `body`. |
| 92 | +1. In the JavaScript `focusin` handler, call a C# method. |
| 93 | + |
| 94 | +>caption Detect Editor focus when using Iframe EditMode |
| 95 | +
|
| 96 | +````RAZOR |
| 97 | +@using Telerik.Blazor.Components.Editor |
| 98 | +
|
| 99 | +@implements IDisposable |
| 100 | +
|
| 101 | +@inject IJSRuntime js |
| 102 | +
|
| 103 | +<TelerikEditor @bind-Value="@EditorValue" |
| 104 | + Tools="@EditorToolSets.All" |
| 105 | + Id="@EditorId" |
| 106 | + Height="300px"> |
| 107 | +</TelerikEditor> |
| 108 | +
|
| 109 | +@* Move JavaScript code to a separate JS file *@ |
| 110 | +<script suppress-error="BL9992"> |
| 111 | + var dotNet; |
| 112 | +
|
| 113 | + function attachIframeFocusHandler(id, dotNetRef) { |
| 114 | + var editor = document.getElementById(id); |
| 115 | + if (editor) { |
| 116 | + dotNet = dotNetRef; |
| 117 | + editor.querySelector("iframe").contentWindow.document.body.addEventListener("focusin", OnEditorBodyFocus); |
| 118 | + } |
| 119 | + } |
| 120 | +
|
| 121 | + function OnEditorBodyFocus(args) { |
| 122 | + dotNet.invokeMethodAsync("OnEditorFocus2"); |
| 123 | + } |
| 124 | +
|
| 125 | + function detachIframeFocusHandler(id) { |
| 126 | + var editor = document.getElementById(id); |
| 127 | + if (editor) { |
| 128 | + editor.querySelector("iframe").contentWindow.document.body.removeEventListener("focusin", OnEditorBodyFocus); |
| 129 | + } |
| 130 | + } |
| 131 | +</script> |
| 132 | +
|
| 133 | +@code { |
| 134 | + #nullable enable |
| 135 | +
|
| 136 | + private string EditorValue { get; set; } = @"<p>foo 2</p><p>bar 2</p>"; |
| 137 | +
|
| 138 | + private const string EditorId = "iframe-editor"; |
| 139 | +
|
| 140 | + // Replace __Main with your Razor component type |
| 141 | + private DotNetObjectReference<Home>? DotNetRef { get; set; } |
| 142 | +
|
| 143 | + [JSInvokable("OnEditorFocus2")] |
| 144 | + public void OnEditorFocus2() |
| 145 | + { |
| 146 | + EditorValue = $"<p>Editor content IFRAME was focused at {DateTime.Now.ToLongTimeString()}.</p>"; |
| 147 | + StateHasChanged(); |
| 148 | + } |
| 149 | +
|
| 150 | + protected override void OnInitialized() |
| 151 | + { |
| 152 | + DotNetRef = DotNetObjectReference.Create(this); |
| 153 | + } |
| 154 | +
|
| 155 | + protected override async Task OnAfterRenderAsync(bool firstRender) |
| 156 | + { |
| 157 | + if (firstRender) |
| 158 | + { |
| 159 | + await Task.Delay(1); // wait for HTML to render |
| 160 | +
|
| 161 | + await js.InvokeVoidAsync("attachIframeFocusHandler", EditorId, DotNetRef); |
| 162 | + } |
| 163 | +
|
| 164 | + await base.OnAfterRenderAsync(firstRender); |
| 165 | + } |
| 166 | +
|
| 167 | + public void Dispose() |
| 168 | + { |
| 169 | + DotNetRef?.Dispose(); |
| 170 | + } |
| 171 | +} |
| 172 | +```` |
| 173 | + |
| 174 | +## See Also |
| 175 | + |
| 176 | +* [Editor Events](slug:editor-events) |
0 commit comments