TinyMCE is a rich-text editor that helps convert the HTML textarea element (or any regular text input element for that matter) into a WYSIWYG editor.
While working with TinyMCE a couple of months ago, I noticed that if our input is a textarea element specifically, and if we’re trying to use AJAX to save text content asynchronously to the database, TinyMCE wouldn’t work well.
I was able to find a hack, and I’ll be explaining the problem as well as the solution in this article. I have written this assuming that you already know how to use TinyMCE, but are only having issues with saving textarea content to the database using AJAX.
First off, when working with TinyMCE and AJAX, our textarea (or text input) element DOES get prettified as expected. So, that is not the problem.
The problem is that, for textarea elements specifically, the text that is entered into the box does not get saved to the database.
Ordinarily, if AJAX is not involved, or if you’re using a regular text input field (even with AJAX), everything works fine. For example, this code works:
<html> <head> <script src="https://link-to-tiny.mce/cdn-or-locally/hosted/tinymce"></script> <script>tinymce.init({ selector:'#description' });</script> </head> <body> <!-- FORM --> <div> <label>Description</label> <input type="text" name="description" id="description" placeholder="Type description here..."> <!-- ...and some submit button that calls the JavaScript saveInfo() function below --> </div> <!-- JavaScript SECTION --> <script> function saveInfo() { event.preventDefault(); // "articleInfo" is a new variable that holds the contents of our text input (or textarea). // It is used later in our AJAX call. articleInfo.append("description", _("description").value); // The rest of the code has been redacted for brevity. // The redacted code includes the actual AJAX call to the PHP server-side function that saves the contents of "articleInfo" to the database. } </script> </body> </html>
Our code above uses a regular HTML text input (input type=”text”) and also uses AJAX. And in this case, everything works perfectly.
However, if you replace the text input field with a textarea field, either nothing from the textarea field is saved to the database, or just the placeholder text gets saved. Or you might even notice that old values are saved on first click while updated values need a second click before they get saved. None of these behaviors are acceptable.
I will share the code to fix this problem below. But first, why does this happen?
This problem happens because TinyMCE converts a textarea field into some sort of iFrame – making it impossible for the textarea field to be treated as a regular form element and having its content sent to a server-side script.
To fix the problem, we need to first call triggerSave() on our tinyMCE object before we perform any AJAX magic.
In this working code snippet below, we are now using a textarea field instead of a regular text input. But in order to avoid the “TinyMCE and AJAX and textarea” problem, we have added a tinyMCE.triggerSave() call before our AJAX section that saves to the database.
<html> <head> <script src="https://link-to-tiny.mce/cdn-or-locally/hosted/tinymce"></script> <script>tinymce.init({ selector:'#description' });</script> </head> <body> <!-- FORM --> <div> <label>Description</label> <textarea name="description" id="description" placeholder="Type description here . . ."></textarea> <!-- ...and some submit button that calls the JavaScript saveInfo() function below --> </div> <!-- JavaScript SECTION --> <script> function saveInfo() { event.preventDefault(); // This line makes TinyMCE work with AJAX when we're using a textarea field. tinyMCE.triggerSave(); // "articleInfo" is a new variable that holds the contents of our text input (or textarea). // It is used later in our AJAX call. articleInfo.append("description", _("description").value); // The rest of the code has been redacted for brevity. // The redacted code includes the actual AJAX call to the PHP server-side function that saves the contents of "articleInfo" to the database. } </script> </body> </html>
In the simplest terms, tinyMCE.triggerSave() deceives the browser, adds an event listener, detects when you click the “submit” button and “reverses” the textarea element to its “natural” state. After that “reversal”, it grabs the content of the textarea, and your code moves to the next section where the data grabbed from the textarea field is handled the same way as any text received from a regular text input field.
The important thing to note is that tinyMCE.triggerSave() must be placed before the AJAX call is made. If you place it after the AJAX call has been made, it would not work, because the data has already been sent.
If you have a smarter way of handling this, please share it with us here.
Leave a Reply