Fix #4358: RichTextEditor Provider Abstraction.
This commit is contained in:
		| @ -1,11 +1,12 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @implements ITextEditor | ||||
| @inject IStringLocalizer<QuillTextEditor> Localizer | ||||
| @inject ISettingService SettingService | ||||
| @inject IStringLocalizer<QuillJSTextEditor> Localizer | ||||
| 
 | ||||
| <div class="quill-text-editor"> | ||||
|     <TabStrip ActiveTab="@_activetab"> | ||||
|         @if (AllowRichText) | ||||
|         @if (_allowRichText) | ||||
|         { | ||||
|             <TabPanel Name="Rich" Heading="Rich Text Editor" ResourceKey="RichTextEditor"> | ||||
|                 @if (_richfilemanager) | ||||
| @ -15,7 +16,7 @@ | ||||
|                     <br /> | ||||
|                 } | ||||
|                 <div class="d-flex justify-content-center mb-2"> | ||||
|                     @if (AllowFileManagement) | ||||
|                     @if (_allowFileManagement) | ||||
|                     { | ||||
|                         <button type="button" class="btn btn-primary" @onclick="InsertRichImage">@Localizer["InsertImage"]</button> | ||||
|                     } | ||||
| @ -28,9 +29,9 @@ | ||||
|                 <div class="row"> | ||||
|                     <div class="col"> | ||||
|                         <div @ref="@_toolBar"> | ||||
|                             @if (ToolbarContent != null) | ||||
|                             @if (!string.IsNullOrEmpty(_toolbarContent)) | ||||
|                             { | ||||
|                                 @ToolbarContent | ||||
|                                 @((MarkupString)_toolbarContent) | ||||
|                             } | ||||
|                             else | ||||
|                             { | ||||
| @ -66,7 +67,7 @@ | ||||
|                 </div> | ||||
|             </TabPanel> | ||||
|         } | ||||
|         @if (AllowRawHtml) | ||||
|         @if (_allowRawHtml) | ||||
|         { | ||||
|             <TabPanel Name="Raw" Heading="Raw HTML Editor" ResourceKey="HtmlEditor"> | ||||
|                 @if (_rawfilemanager) | ||||
| @ -76,7 +77,7 @@ | ||||
|                     <br /> | ||||
|                 } | ||||
|                 <div class="d-flex justify-content-center mb-2"> | ||||
|                     @if (AllowFileManagement) | ||||
|                     @if (_allowFileManagement) | ||||
|                     { | ||||
|                         <button type="button" class="btn btn-primary" @onclick="InsertRawImage">@Localizer["InsertImage"]</button> | ||||
|                     } | ||||
| @ -106,6 +107,14 @@ | ||||
|     private FileManager _fileManager; | ||||
|     private string _activetab = "Rich"; | ||||
| 
 | ||||
|     private bool _allowFileManagement = false; | ||||
|     private bool _allowRawHtml = false; | ||||
|     private bool _allowRichText = false; | ||||
|     private string _theme = "snow"; | ||||
|     private string _debugLevel = "info"; | ||||
|     private string _toolbarContent = string.Empty; | ||||
|     private bool _settingsLoaded; | ||||
| 
 | ||||
|     private ElementReference _editorElement; | ||||
|     private ElementReference _toolBar; | ||||
|     private bool _richfilemanager = false; | ||||
| @ -121,38 +130,22 @@ | ||||
|     private bool _contentchanged = false; | ||||
|     private int _editorIndex; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowFileManagement{ get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowRichText { get; set; } = true; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool AllowRawHtml { get; set; } = true; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public bool ReadOnly { get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string Placeholder { get; set; } | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string Theme { get; set; } = "snow"; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public string DebugLevel { get; set; } = "info"; | ||||
| 
 | ||||
|     [Parameter] | ||||
|     public RenderFragment ToolbarContent { get; set; } | ||||
| 
 | ||||
|     public override List<Resource> Resources { get; set; } = new List<Resource>() | ||||
|     { | ||||
|         new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill.min.js", Location = ResourceLocation.Body }, | ||||
|         new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-blot-formatter.min.js", Location = ResourceLocation.Body }, | ||||
|         new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body } | ||||
|         new Resource { ResourceType = ResourceType.Script, Bundle = "Quill", Url = "js/quill-interop.js", Location = ResourceLocation.Body }, | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.bubble.css" }, | ||||
|         new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill.snow.css" } | ||||
|     }; | ||||
| 
 | ||||
|     protected override void OnInitialized() | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         interop = new QuillEditorInterop(JSRuntime); | ||||
| 
 | ||||
| @ -160,11 +153,13 @@ | ||||
|         { | ||||
|             Placeholder = Localizer["Placeholder"]; | ||||
|         } | ||||
| 
 | ||||
|         await LoadSettings(); | ||||
|     } | ||||
| 
 | ||||
|     protected override void OnParametersSet() | ||||
|     { | ||||
|         if (!AllowRichText) | ||||
|         if (!_allowRichText) | ||||
|         { | ||||
|             _activetab = "Raw"; | ||||
|         } | ||||
| @ -174,17 +169,17 @@ | ||||
|     { | ||||
|         await base.OnAfterRenderAsync(firstRender); | ||||
| 
 | ||||
|         if (AllowRichText) | ||||
|         if (_allowRichText) | ||||
|         { | ||||
|             if (firstRender) | ||||
|             if (_settingsLoaded && !_initialized) | ||||
|             { | ||||
|                 await interop.CreateEditor( | ||||
|                     _editorElement, | ||||
|                     _toolBar, | ||||
|                     ReadOnly, | ||||
|                     Placeholder, | ||||
|                     Theme, | ||||
|                     DebugLevel); | ||||
|                     _theme, | ||||
|                     _debugLevel); | ||||
| 
 | ||||
|                 await interop.LoadEditorContent(_editorElement, _richhtml); | ||||
| 
 | ||||
| @ -202,6 +197,8 @@ | ||||
|                         // reload editor if Content passed to component has changed | ||||
|                         await interop.LoadEditorContent(_editorElement, _richhtml); | ||||
|                         _originalrichhtml = await interop.GetHtml(_editorElement); | ||||
| 
 | ||||
|                         _contentchanged = false; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
| @ -215,8 +212,6 @@ | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             _contentchanged = false; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -224,10 +219,14 @@ | ||||
|     { | ||||
|         _richhtml = content; | ||||
|         _rawhtml = content; | ||||
|         _originalrawhtml = _rawhtml; // preserve for comparison later | ||||
|         _originalrichhtml = ""; | ||||
|         _richhtml = content; | ||||
|         _contentchanged = content != _originalrawhtml; | ||||
|         if (!_contentchanged) | ||||
|         { | ||||
|             _contentchanged = content != _originalrawhtml; | ||||
|         } | ||||
| 
 | ||||
|         _originalrawhtml = _rawhtml; // preserve for comparison later | ||||
| 
 | ||||
|         StateHasChanged(); | ||||
|     } | ||||
| @ -243,7 +242,7 @@ | ||||
|         { | ||||
|             var richhtml = ""; | ||||
| 
 | ||||
|             if (AllowRichText) | ||||
|             if (_allowRichText) | ||||
|             { | ||||
|                 richhtml = await interop.GetHtml(_editorElement); | ||||
|             } | ||||
| @ -290,7 +289,7 @@ | ||||
|         { | ||||
|             var richhtml = ""; | ||||
| 
 | ||||
|             if (AllowRichText) | ||||
|             if (_allowRichText) | ||||
|             { | ||||
|                 richhtml = await interop.GetHtml(_editorElement); | ||||
|             } | ||||
| @ -362,4 +361,24 @@ | ||||
|         } | ||||
|         StateHasChanged(); | ||||
|     } | ||||
| 
 | ||||
|     private async Task LoadSettings() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             _allowFileManagement = SettingService.GetSetting(settings, "QuillTextEditor_AllowFileManagement", "true") == "true"; | ||||
|             _allowRawHtml = SettingService.GetSetting(settings, "QuillTextEditor_AllowRawHtml", "true") == "true"; | ||||
|             _allowRichText = SettingService.GetSetting(settings, "QuillTextEditor_AllowRichText", "true") == "true"; | ||||
|             _theme = SettingService.GetSetting(settings, "QuillTextEditor_Theme", "snow"); | ||||
|             _debugLevel = SettingService.GetSetting(settings, "QuillTextEditor_DebugLevel", "info"); | ||||
|             _toolbarContent = SettingService.GetSetting(settings, "QuillTextEditor_ToolbarContent", string.Empty); | ||||
| 
 | ||||
|             _settingsLoaded = true; | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,99 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleBase | ||||
| @inject ISettingService SettingService | ||||
| @implements Oqtane.Interfaces.ISettingsControl | ||||
| @inject IStringLocalizer<QuillJSTextEditorSettings> Localizer | ||||
| @inject IStringLocalizer<SharedResources> SharedLocalizer | ||||
|  | ||||
| <div class="container"> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowFileManagement" ResourceKey="AllowFileManagement" ResourceType="@resourceType" HelpText="Specify If Editors Can Upload and Select Files">Allow File Management: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowFileManagement" class="form-check-input" @bind="_allowFileManagement" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowRawHtml" ResourceKey="AllowRawHtml" ResourceType="@resourceType" HelpText="Specify If Editors Can Enter Raw HTML">Allow Raw HTML: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowRawHtml" class="form-check-input" @bind="_allowRawHtml" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="AllowRichText" ResourceKey="AllowRichText" ResourceType="@resourceType" HelpText="Specify If Editors Can Use Rich Text Editor">Allow Rich Text: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="checkbox" id="AllowRichText" class="form-check-input" @bind="_allowRichText" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="Theme" ResourceKey="Theme" ResourceType="@resourceType" HelpText="Specify the Rich Text Editor's Theme">Theme: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <input type="text" id="Theme" class="form-control" @bind="_theme" /> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="DebugLevel" ResourceKey="DebugLevel" ResourceType="@resourceType" HelpText="Specify the Debug Level">Debug Level: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <select id="DebugLevel" class="form-select" @bind="_debugLevel"> | ||||
|                 @foreach (var level in _debugLevels) | ||||
|                 { | ||||
|                     <option value="@level">@level</option> | ||||
|                 } | ||||
|             </select> | ||||
|         </div> | ||||
|     </div> | ||||
|     <div class="row mb-1 align-items-center"> | ||||
|         <Label Class="col-sm-3" For="ToolbarContent" ResourceKey="ToolbarContent" ResourceType="@resourceType" HelpText="Specify the Toolbar Content">Toolbar Content: </Label> | ||||
|         <div class="col-sm-9"> | ||||
|             <textarea id="ToolbarContent" class="form-control" @bind="_toolbarContent" rows="5" /> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private string resourceType = "Oqtane.Modules.Controls.QuillJSTextEditorSettings, Oqtane.Client"; | ||||
|     private bool _allowFileManagement; | ||||
|     private bool _allowRawHtml; | ||||
|     private bool _allowRichText; | ||||
|     private string _theme; | ||||
|     private string _debugLevel; | ||||
|     private string _toolbarContent; | ||||
|  | ||||
|     private List<string> _debugLevels = new List<string> { "info", "log", "warn", "error" }; | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             _allowFileManagement = SettingService.GetSetting(settings, "QuillTextEditor_AllowFileManagement", "true") == "true"; | ||||
|             _allowRawHtml = SettingService.GetSetting(settings, "QuillTextEditor_AllowRawHtml", "true") == "true"; | ||||
|             _allowRichText = SettingService.GetSetting(settings, "QuillTextEditor_AllowRichText", "true") == "true"; | ||||
|             _theme = SettingService.GetSetting(settings, "QuillTextEditor_Theme", "snow"); | ||||
|             _debugLevel = SettingService.GetSetting(settings, "QuillTextEditor_DebugLevel", "info"); | ||||
|             _toolbarContent = SettingService.GetSetting(settings, "QuillTextEditor_ToolbarContent", string.Empty); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public async Task UpdateSettings() | ||||
|     { | ||||
|         try | ||||
|         { | ||||
|             var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowFileManagement", _allowFileManagement.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowRawHtml", _allowRawHtml.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_AllowRichText", _allowRichText.ToString().ToLower()); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_Theme", _theme); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_DebugLevel", _debugLevel); | ||||
|             settings = SettingService.SetSetting(settings, "QuillTextEditor_ToolbarContent", _toolbarContent); | ||||
|             await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId); | ||||
|         } | ||||
|         catch (Exception ex) | ||||
|         { | ||||
|             AddModuleMessage(ex.Message, MessageType.Error); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -4,7 +4,6 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @inject IServiceProvider ServiceProvider | ||||
| @inject ISettingService SettingService | ||||
| @inject IStringLocalizer<RichTextEditor> Localizer  | ||||
|  | ||||
| <div class="row" style="margin-bottom: 50px;"> | ||||
| @ -14,7 +13,7 @@ | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private ITextEditorProvider _textEditorProvider; | ||||
|     private string _textEditorProvider; | ||||
|     private RenderFragment _textEditorComponent; | ||||
|     private ITextEditor _textEditor; | ||||
|  | ||||
| @ -28,29 +27,14 @@ | ||||
|     public string Placeholder { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowFileManagement { get; set; } = true; | ||||
|     public string Provider { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowRichText { get; set; } = true;   | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool AllowRawHtml { get; set; } = true;   | ||||
|  | ||||
|     // parameters only applicable to rich text editor | ||||
|     [Parameter] | ||||
|     public RenderFragment ToolbarContent { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string Theme { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string DebugLevel { get; set; } | ||||
|  | ||||
|     public override List<Resource> Resources { get; set; } = new List<Resource>(); | ||||
|     [Parameter(CaptureUnmatchedValues = true)] | ||||
|     public Dictionary<string, object> AdditionalAttributes { get; set; } = new Dictionary<string, object>(); | ||||
|  | ||||
|     protected override async Task OnInitializedAsync() | ||||
|     { | ||||
|         _textEditorProvider = await GetTextEditorProvider(); | ||||
|         _textEditorProvider = await GetTextEditorType(ServiceProvider, PageState.Site.SiteId); | ||||
|     } | ||||
|  | ||||
|     protected override void OnParametersSet() | ||||
| @ -71,6 +55,22 @@ | ||||
|         await base.OnAfterRenderAsync(firstRender); | ||||
|     } | ||||
|  | ||||
|     public override async Task<List<Resource>> GetResources(IServiceProvider serviceProvider, Page page) | ||||
|     { | ||||
|         var type = await GetTextEditorType(serviceProvider, page.SiteId); | ||||
|         if (!string.IsNullOrEmpty(type)) | ||||
|         { | ||||
|             var editorType = Type.GetType(type); | ||||
|             if (editorType != null && editorType.GetInterfaces().Contains(typeof(IModuleControl))) | ||||
|             { | ||||
|                 var control = Activator.CreateInstance(editorType) as IModuleControl; | ||||
|                 return await control?.GetResources(serviceProvider, page); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return await base.GetResources(serviceProvider, page); | ||||
|     } | ||||
|  | ||||
|     public async Task<string> GetHtml() | ||||
|     { | ||||
|         return await _textEditor.GetContent(); | ||||
| @ -78,37 +78,32 @@ | ||||
|  | ||||
|     private void CreateTextEditor(RenderTreeBuilder builder) | ||||
|     { | ||||
|         if(_textEditorProvider != null) | ||||
|         if(!string.IsNullOrEmpty(_textEditorProvider)) | ||||
|         { | ||||
|             var editorType = Type.GetType(_textEditorProvider.EditorType); | ||||
|             var editorType = Type.GetType(_textEditorProvider); | ||||
|             if (editorType != null) | ||||
|             { | ||||
|                 builder.OpenComponent(0, editorType); | ||||
|  | ||||
|                 //set editor parameters if available. | ||||
|                 var attributes = new Dictionary<string, object> | ||||
|                 { | ||||
|                     { "AllowFileManagement", AllowFileManagement }, | ||||
|                     { "AllowRichText", AllowRichText }, | ||||
|                     { "AllowRawHtml", AllowRawHtml }, | ||||
|                     { "Placeholder", Placeholder }, | ||||
|                     { "ReadOnly", ReadOnly } | ||||
|                 }; | ||||
|  | ||||
|                 if(!string.IsNullOrEmpty(Theme)) | ||||
|                 if (AdditionalAttributes != null) | ||||
|                 { | ||||
|                     attributes.Add("Theme", Theme); | ||||
|                 } | ||||
|                 if (!string.IsNullOrEmpty(DebugLevel)) | ||||
|                 { | ||||
|                     attributes.Add("DebugLevel", DebugLevel); | ||||
|                 } | ||||
|                 if (!string.IsNullOrEmpty(Placeholder)) | ||||
|                 { | ||||
|                     attributes.Add("Placeholder", Placeholder); | ||||
|                 } | ||||
|                 if(ToolbarContent != null) | ||||
|                 { | ||||
|                     attributes.Add("ToolbarContent", ToolbarContent); | ||||
|                     foreach(var key in AdditionalAttributes.Keys) | ||||
|                     { | ||||
|                         if(!attributes.ContainsKey(key)) | ||||
|                         { | ||||
|                             attributes.Add(key, AdditionalAttributes[key]); | ||||
|                         } | ||||
|                         else | ||||
|                         { | ||||
|                             attributes[key] = AdditionalAttributes[key]; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 var index = 1; | ||||
| @ -129,26 +124,21 @@ | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private async Task<ITextEditorProvider> GetTextEditorProvider() | ||||
|     private async Task<string> GetTextEditorType(IServiceProvider serviceProvider, int siteId) | ||||
|     { | ||||
|         const string DefaultEditorName = "Quill"; | ||||
|         const string EditorSettingName = "TextEditorProvider"; | ||||
|  | ||||
|         var editorName = await GetTextEditorName(DefaultEditorName); | ||||
|         var editorProviders = ServiceProvider.GetServices<ITextEditorProvider>(); | ||||
|         var editorProvider = editorProviders.FirstOrDefault(i => i.Name == editorName); | ||||
|         if(editorProvider == null) | ||||
|         if(!string.IsNullOrEmpty(Provider)) | ||||
|         { | ||||
|             editorProvider = editorProviders.FirstOrDefault(i => i.Name == DefaultEditorName); | ||||
|             var provider = serviceProvider.GetServices<ITextEditorProvider>().FirstOrDefault(i => i.Name.Equals(Provider, StringComparison.OrdinalIgnoreCase)); | ||||
|             if(provider != null) | ||||
|             { | ||||
|                 return provider.EditorType; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return editorProvider; | ||||
|     } | ||||
|  | ||||
|     private async Task<string> GetTextEditorName(string defaultName) | ||||
|     { | ||||
|         const string EditorSettingName = "TextEditor"; | ||||
|  | ||||
|         var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId); | ||||
|         return SettingService.GetSetting(settings, EditorSettingName, defaultName); | ||||
|         var settingService = serviceProvider.GetService<ISettingService>(); | ||||
|         var settings = await settingService.GetSiteSettingsAsync(siteId); | ||||
|         return settingService.GetSetting(settings, EditorSettingName, Constants.DefaultTextEditorProvider); | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										31
									
								
								Oqtane.Client/Modules/Controls/TextAreaTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Oqtane.Client/Modules/Controls/TextAreaTextEditor.razor
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| @namespace Oqtane.Modules.Controls | ||||
| @inherits ModuleControlBase | ||||
| @implements ITextEditor | ||||
|  | ||||
| <div class="text-area-editor"> | ||||
|     <textarea @bind="_content" @ref="_editor" placeholder="@Placeholder" readonly="@ReadOnly" /> | ||||
| </div> | ||||
|  | ||||
| @code { | ||||
|     private ElementReference _editor; | ||||
|     private string _content; | ||||
|  | ||||
|     [Parameter] | ||||
|     public bool ReadOnly { get; set; } | ||||
|  | ||||
|     [Parameter] | ||||
|     public string Placeholder { get; set; } | ||||
|  | ||||
|     public void Initialize(string content) | ||||
|     { | ||||
|         _content = content; | ||||
|  | ||||
|         StateHasChanged(); | ||||
|     } | ||||
|  | ||||
|     public async Task<string> GetContent() | ||||
|     { | ||||
|         await Task.CompletedTask; | ||||
|         return _content; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Ben
					Ben