CKEditor 5 asks to set <div> instead of <textarea>, but then asp-for does not work for @Model.Class.Value (always = null).

Volk Volk 571 Reputation points
2023-07-30T18:17:58.83+00:00

Hi!

I am trying to create a text input field for a client based on CKEditor 5.

This is not a classic CKEditor. The classic one just needs to specify <textarea> and everything works:

<textarea id="editor_middle_en" asp-for="ProjectProduct.MiddleDescription_en">@Html.Raw(Model.ProjectProduct.MiddleDescription_en)</textarea>

But the custom CKEditor requires me to put not <textarea>, <div>:
<div id="editor_middle_en" asp-for="ProjectProduct.MiddleDescription_en">@Html.Raw(Model.ProjectProduct.MiddleDescription_en)</div>

asp-for with <div> always sends me null in @Model.Project Product.MiddleDescription_en in the controller method, which I call using submit:

<input id="submit" class="btn btn-info" hidden type="submit" value="submit"/>

How do I transfer the actual text from CKEditor 5 <div>? I tried doing hidden input - it works, but it's a separate block and the text doesn't change there. I also tried to pick up the actual text from <div> using oninput=Method(this);", but in the console I see an error like domconverter-unsafe-attribute-detected.

Thanks!

[HttpPost]
public IActionResult Method(Model? model) {
	model.ProjectProduct.MiddleDescription_en = null; !!!
}
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,400 questions
{count} votes

Accepted answer
  1. AgaveJoe 1,495 Reputation points
    2023-07-31T18:32:09.21+00:00

    I do not create Classic Editor, I use Decoupled Editor. I did as you advised.

    This is why the community asks for the source code. There are several CKEditor 5 default builds each use the same API. Since the decoupled-document build uses the Decoupled Editor, I'll use the decoupled-document build in the example.

    https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/predefined-builds.html#document-editor

    I have this error in the console:

    The error message indicates "editor" is not initialized or pointing to the right place. I assume there is a bug in your code which we cannot see.

    @{
        ViewData["Title"] = "Index";
    }
    <h1>Document editor</h1>
    
    <div id="toolbar-container"></div>
    
    <div id="editor">
        <p>This is the initial editor content.</p>
    </div>
    <div>
        <button id="submitButton" type="button">Submit</button>
    </div>
    
    @section scripts {
        <script src="https://cdn.ckeditor.com/ckeditor5/38.1.1/decoupled-document/ckeditor.js"></script>
    
    
        <script>
            let decoupledEditor;
    
            DecoupledEditor
                .create(document.querySelector('#editor'))
                .then(editor => {
                    const toolbarContainer = document.querySelector('#toolbar-container');
    
                    toolbarContainer.appendChild(editor.ui.view.toolbar.element);
                    decoupledEditor = editor;
                        })
                .catch(error => {
                    console.error(error);
                });
    
            document.querySelector('#submitButton').addEventListener('click', () => {
                const editorData = decoupledEditor.getData();
                console.log(editorData);
            });
    
        </script>
    }
    
    
    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. AgaveJoe 1,495 Reputation points
    2023-07-31T14:38:38.4566667+00:00

    How do I transfer the actual text from CKEditor 5 <div>?

    According to the CkEditor 5 documentation, JavaScript is used to fetch the editor contents.

    https://ckeditor.com/docs/ckeditor5/latest/installation/getting-started/getting-and-setting-data.html

    I used the fetch API to submit the editor contents to the the controller.

    https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

    Model

        public class MyModel
        {
            public string EditorData { get; set; }
        }
    

    View

    
    @{
        ViewData["Title"] = "Index";
    }
    
    <div class="text-center">
        <h1>Welcome to CKEditor 5 in .NET</h1>
        <div id="editor"></div>
        <div>
            <button id="submit" type="button">Submit</button>
        </div>
    </div>
    
    
    @section scripts { 
        <script src="https://cdn.ckeditor.com/ckeditor5/38.1.1/classic/ckeditor.js"></script>
        <script>
            let editor;
    
            ClassicEditor
                .create(document.querySelector('#editor'))
                .then(newEditor => {
                    editor = newEditor;
                })
                .catch(error => {
                    console.error(error);
                });
    
            document.querySelector('#submit').addEventListener('click', () => {
                const editorData = editor.getData();
    
                console.log(editorData);
    
                const data = { EditorData: editorData };
                postJSON(data);
            });
    
    
            // Example POST method implementation:
            async function postJSON(data) {
                try {
                    const response = await fetch("/CkEditor", {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                        },
                        body: JSON.stringify(data),
                    });
                    const result = await response.json();
                    console.log("Success:", result);
                } catch (error) {
                    console.error("Error:", error);
                }
            }
        </script>
    }
    
    

    Controller

        public class CkEditorController : Controller
        {
            [HttpGet]
            public IActionResult Index()
            {
                return View();
            }
    
            [HttpPost]
            public IActionResult Index([FromBody] MyModel data)
            {
                return Ok(data);
            }
        }
    
    0 comments No comments

  2. Bruce (SqlWork.com) 61,731 Reputation points
    2023-07-31T16:40:09.9+00:00

    browsers do not post div values. you should use javascript to copy the div html to a hidden field before submitting.

    also razor <div>'s don't support asp-for, you should change the div to:

    <div id="editor_middle_en">@Html.Raw(Model.ProjectProduct.MiddleDescription_en)</div>

    and be sure MiddleDescription_en is valid html.