Search code examples
ckeditorckeditor4.x

Text in CKEDITOR field not being submitted in the first submission


The text in ckeditor field is not sent when submitting forms for the first time (only on the second time, third time, etc).

For example, If try to create an article's post and submit the form I'll get a validation error: 'The field body is required'. If try to submit again (for the second time or third time), It will work well.

The real problem is when editing! For example, when editing a form the field 'body', among others fields, is filled out with the data from the database. In other words, there are already text in the ckeditor field.

If I try to submit the form for the first time it will not update the body because the text in the ckeditor is not sent; what is sent is the default value (the old article's body, which was filled out with data from the DB).

Therefore, it won't edit unless I get a validation error in other field (if I get a validation error, I'll have to submit again, and that will work).

How to solve this problem? Is this an known bug in CKEDITOR 4? If I don't solve it the users will feel frustrated if they have to submit the form at least twice to edit or to create an article.

Here is a list of plugins I'm using (may be useful to solve the problem):

a11yhelp, about, api, autocomplete, autocorrect, browser, clipboard, colordialog, copyformatting, crossereference, dialog, div, docprops, find, googlesearch, image, link, liststyle, magicline, mathjax, openlink, pastecode, pastefromword, preview, quicktable, scayt, section, showblocks, sourcedialog, specialchar, table, tableselection, tabletools, tabletoolstoolbar, texttransform, widget, wsc

By the way, I downloaded ckeditor using ckeditor builder in their official website.


Solution

  • I opened this issue in GitHub and a guy figured out the problem. His proposed solution worked wel!! Here is what he said:

    Workaround

    As the issue is more tricky to fix than it seems, for now I propose a simple workaround: invoke ajaxRequest not on $( document ).ready, but rather on editor's loaded event:

    CKEDITOR.replace( 'editor', {
      on: { 
             loaded: function() {ajaxRequest();}
          }
      });
    

    Explanation of the issue

    The issue is connected with how DOM listeners are registered for given element:

    The order of event listeners for a particular event type will always be:

    • The event listeners registered with addEventListener() before the first time the event handler's value was set to non-null
    • Then the callback to which it is currently set, if any
    • Finally, the event listeners registered with addEventListener() after the first time the event handler's value was set to non-null.

    In case of CKEditor 4, the value of the form's element is modified by editor._attachToForm private method, which adds event listener to form's submit event:

    ckeditor-dev/core/editor.js form.on( 'submit', onSubmit );

    However this listener is added on loaded event, which is fired asynchronously when editor is loaded – so after registering synchronous onsubmit handler with the validation logic. This way editor's field is updated after validating.

    Proposed solutions

    Update editor's element on formdata event. This way we would have total control over data being submitted and we would be sure that correct data is set before submit event. The problem with this solution is the fact that browsers' support is non-existent; the event will appear in Chrome 77, however it is still not known if and when the support will appear in Firefox or Safari.

    Update editor's element on every change in the editor's content thanks to change event. This solution will also fix cases, where some other scripts are using value not from the editor, but directly from the replaced textarea – they would get fresh data more often then only after submitting the form. However this solution requires #1364, which connects with a pretty big refactoring.

    NOTE: AjaxRequest is the function I was using to submit the form togehter with Jquery.