我正在尝试将CKeditor与Blazor一起使用。我使用在线构建器创建了一个自定义构建,使用ImageUpload和Base64UploadAdapter,它集成在BlazorApp中。
我可以成功地在页面上显示它,并从中放入/获取HTML内容。Blazor应用程序的工作版本来源如下https://gitlab.com/dn-misc/BlazorCKEditor1/
但由于我想直接在HTML内容中插入Base64编码字符串的图像,当我尝试上传图像时,我会收到以下错误:断言失败:输入参数不是HTMLInputElement(来自contentscript.js(
我已经成功地实现了Chris Pratt的实现。看看这个:
重要提示:这仅适用于ClassicEditor
Blazor组件,我称之为InputCKEditor.rarzor。是的,我知道,不是很原始。
@namespace SmartApp.Components
@inherits InputTextArea
@inject IJSRuntime JSRuntime
<textarea @attributes="AdditionalAttributes"
id="@Id"
class="@CssClass"
value="@CurrentValue"></textarea>
@code {
string _id;
[Parameter]
public string Id
{
get => _id ?? $"CKEditor_{_uid}";
set => _id = value;
}
readonly string _uid = Guid.NewGuid().ToString().ToLower().Replace("-", "");
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
await JSRuntime.InvokeVoidAsync("CKEditorInterop.init", Id, DotNetObjectReference.Create(this));
await base.OnAfterRenderAsync(firstRender);
}
[JSInvokable]
public Task EditorDataChanged(string data)
{
CurrentValue = data;
StateHasChanged();
return Task.CompletedTask;
}
protected override void Dispose(bool disposing)
{
JSRuntime.InvokeVoidAsync("CKEditorInterop.destroy", Id);
base.Dispose(disposing);
}
}
然后,您必须将其放入interop.js中
CKEditorInterop = (() => {
var editors = {};
return {
init(id, dotNetReference) {
window.ClassicEditor
.create(document.getElementById(id))
.then(editor => {
editors[id] = editor;
editor.model.document.on('change:data', () => {
var data = editor.getData();
var el = document.createElement('div');
el.innerHTML = data;
if (el.innerText.trim() === '')
data = null;
dotNetReference.invokeMethodAsync('EditorDataChanged', data);
});
})
.catch(error => console.error(error));
},
destroy(id) {
editors[id].destroy()
.then(() => delete editors[id])
.catch(error => console.log(error));
}
};
})();
现在是时候使用它了:
<form>
<label class="col-xl-3 col-lg-3 col-form-label text-sm-left text-lg-right">Description</label>
<div class="col-lg-9 col-xl-6">
<InputCKEditor @bind-Value="_model.Description" class="form-control form-control-solid form-control-lg"></InputCKEditor>
<ValidationMessage For="@(() => _model.Description)" />
</div>
</form>
我对@Javier编写的代码有一个小问题。
在我的代码中,我传递了一个配置参数(以及dotNetReference
(,这样我们就可以根据配置脚本为不同的页面更改CKEditor的外观。初始化CKEditor时,dotNetReference
变量始终为"未定义"。
因此,在InputCKEditor.razor
中,当调用await JSRuntime.InvokeVoidAsync("CKEditorInterop.init", Id, DotNetObjectReference.Create(this));
时,我首先将DotNetObjectReference.Create(this)
实例化为变量。然后,当javascript运行时,它有一个实例化的对象。
.js代码(注意:附加的configFunction
参数(
CKEditorInterop = (() => {
return {
init(id, configFunction, dotNetReference) {
CKEDITOR.replace(id, {
extraAllowedContent: 'b i div class strong table th tr td label div class [*] {*}',
});
for (var i in CKEDITOR.instances) {
CKEDITOR.instances[i].on('change', function () {
var data = CKEDITOR.instances[i].getData();
var el = document.createElement('div');
el.innerHTML = data;
if (el.innerText.trim() === '')
data = null;
dotNetReference.invokeMethodAsync('EditorDataChanged', data);
});
}
if (configFunction !== undefined && configFunction !== 'null') {
var fn = window[configFunction];
fn(id);
}
},
destroy(id) {
CKEDITOR.instances[id].desctoy();
}
};
})();
C#代码:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender) {
var obj = DotNetObjectReference.Create(this); // *** Instanciated here and this populated the object passed into the javascript ***
await JSRuntime.InvokeVoidAsync("CKEditorInterop.init", Id, obj);
}
await base.OnAfterRenderAsync(firstRender);
}
我不确定为什么我需要这样做,但它解决了我的问题。