A rich text editor lets your users enter, edit, and format text in your site. It looks like this:
You create a rich text editor using the Wix HTML element and then use code to save the formatted text in a rich text type field in a collection.
Before continuing in this post you should read the Messaging section in this article to familiarize yourself with how the HTML element works with Wix Code.
We’ll give you step by step instructions below, but first, the big picture. To make this work you need to have an HTML element and a button talk to each other. This follows the following pattern:
The page code sends a message to the HTML element.
The HTML element receives the message.
Receiving the message triggers the HTML element to send a message to the page code with the contents of the rich text editor.
The page code receives the message from the HTML element and reads the contents of the rich text editor from the sent message.
Then all you need to do is take that data and insert it in a collection.
Now for the details:
Add a button and an HTML element to your page (the HTML element is under “More”).
Select the HTML element and add this code to it. It has both HTML and JavaScript comments in it.
<!doctype html>
<html>
<head>
<!--Define the character set for the HTML element -->
<meta charset="utf-8">
<!--Call the external script to use the CDN CKEditor in your page-->
<script src="//cdn.ckeditor.com/4.6.2/standard/ckeditor.js"></script>
<script type="text/javascript">
//Define an init function that sends the rich text editor contents to the page code
function init() {
//onMessage runs when the HTML element receives a message from the page code
window.onmessage = (event) => {
if (event.data) {
//postMessage sends the contents of the CKEDITOR back to the page code
window.parent.postMessage(CKEDITOR.instances.CK1.getData(),"*");
}
}
}
</script>
</head>
<body onload="init();">
<!--Define the HTML element as a textarea-->
<textarea name="editor1" id="CK1"></textarea>
<script>
//Use the CKEditor replace() function to turn our textarea into a CKEditor rich text editor
CKEDITOR.replace("editor1");
</script>
</body>
</html>
Add an onClick event handler to the button.
Add this code to the onClick event handler:
//Send a blank message to the HTML element. This tells the HTML element you want it to send you its contents
$w("#html1").postMessage(" ");
//Receive the message from the HTML element
$w("#html1").onMessage((event) => {
//Create an object named "rich" from the data in the rich text editor to insert into the collection
const rich = {
"richtext": event.data
};
//Insert the "rich" object into the collection
wixData.insert("new-collection", rich)
//Log an error if the insert fails
.catch((err) => {
console.log("error", err);
});
});
Some “Don’t forget” things:
You need to add import wixData from “wix-data” to the top of your page code.
This example works with the following in the page code:
- A collection named “new-collection”
- A richtext field named “richtext”
- An html element named “html1”
You’ll need to replace these in the code with the corresponding names for those items in your site.
Last notes:
The HTML element’s functionality isn’t perfect in preview, so you’ll need to test this on your published site. Don’t forget to look at your Live Data to check that it worked.
If the data looks like it has some weird codes in it, just double click the cell to open the rich text editor for the rich text field in the Content Manager. You’ll see the data formatted as it was entered on the site.
If you want to later display rich text in a text element you should read this to understand how rich text formatting works with the formatting settings and themes in the editor.
-Jeff
Thank you for this information! It almost works for me. However I’m having an issue, that when submitting the rich text along with other data fields, the rich text doesn’t appear in the same row along with the rest of the data in the database, rather on it’s own in a separate row. How do I get all submitted information into the same row?
Hey Vincent,
It sounds like you created another button and set it up to submit. In the code above we use insert to create a new item in the collection. But if you have other data and are using a submit button to save it, you want to use the setFieldValue function to add your rich text to the item you are submitting and save it all together.
Since you are going to insert data into your collection from 2 places (your input elements and your HTML element) you’ll need to set up the submit manually so it grabs both those bits of data. To do that you should remove the extra submit button you created. We’ll add code to the button we originally added above to handle that. Now, when the user clicks that button two things will happen:
It will trigger the communication between the HTML element and the page code, like before.
It will take the rich text content from the HTML element and set it to be the field value for the rich text field in your collection. This is where we’ll use the setFieldValue function .
Here’s what the code in the click event for your button should look like now:
export function button1_click_(event, $w) {
//Send a blank message to the HTML element. This tells the HTML
//element you want it to send you its contents
$w("#html1").postMessage(" ");
//Receive the message from the HTML element
$w("#html1").onMessage((event) => {
//Set the value for the rich text field of the dataset's
//current item to be the data in the HTML element
$w("#dataset1").setFieldValue("richtextField", event.data);
//Submit the current item of the dataset
$w("#dataset1").save();
});
}
Same "Don’t forget"s and “Notes” as above. Also richtextField needs to be replaced with the field key for your rich text field in your collection.
I’m experiencing the same problem as Vincent, then concluded to replace the initial code under the button with your new bit of code, but I’m afraid that now it no longer works…
What I did pick up is that when I forget to enter one of the mandatory fields before submitting, then submit and get an error, populating the mandatory field and then submitting again, it works.
I tried adding an onBeforeSave event handler, but no luck. any advice?
Code below:
export function button1_click(event) {
$w(“#dataset1”).onBeforeSave()( () => {
//Send a blank message to the HTML element. This tells the HTML
//element you want it to send you its contents
$w(“#html1”).postMessage(" “);
//Receive the message from the HTML element
$w(”#html1").onMessage((event) => {
//Set the value for the rich text field of the dataset’s
//current item to be the data in the HTML element
$w(“#dataset1”).setFieldValue(“biography”, event.data);
});
//Submit the current item of the dataset
$w(“#dataset1”).save();
});
}
I did receive the code but when I added it to the end of the page it is not working for some reason.
I clicked on the Gallery
Clicked on onCurrentitemChanged on the properties panel
Pasted the whole script after the the lat }
Hi, thank you so much for this Jeff. Can we add more fonts to this? How?
And as Tiaan has said, this code doesn’t seem to be working when combining with other user inputs?
export function submit_onClick_(event, $w) {
//Send a blank message to the HTML element. This tells the HTML
//element you want it to send you its contents
$w(“#html1”).postMessage(" “);
//Receive the message from the HTML element
$w(”#html1").onMessage((event) => {
//Set the value for the rich text field of the dataset’s
//current item to be the data in the HTML element
$w(“#dataset2”).setFieldValue(“longDescription”, event.data);
//Submit the current item of the dataset
$w(“#dataset2”).save();
});
}
Also, we really need a success message or something so you know it has worked.
Just a reminder in case this is part of the problem - the button we are using is using code to manually trigger the submit, you can’t use the submit action in the connect to data panel to do the submit. If you did it will conflict with the code and this won’t work, and you need to remove that action.
Tiaan - I saw that your code doesn’t match what I have in that you have the dataset.save outside the onMessage function and mine is inside. Again, here is mine (without the comments):
Splatty - I don’t see anything wrong with your code so unless the submit action I mentioned above is the problem, I can’t tell from here. If you send me your site URL I can take a look.
About a success message - we’ve got that. See here.
If I’m understanding this correctly, this page is meant to create new entries in your collection, not edit existing ones. If that’s the case your dataset needs to be set to write-only, not read-write.
As far as I could see, you didn’t connect all of your input elements to your dataset. Property information, Location, Type and the image upload weren’t connected.
In your onClick event you set all your input values to null or 0 before you execute the save, so you’re not going to save the user input. I realize you want to clear the form after the save, but you are doing it too early. The way to that is to add a .then to the save, since it returns a promise. Also you may want to set the value to undefined , not null or zero. This resets the fields so no option is selected. If you want them to have a selection you can replace undefined with null and zero as you had it.
export function submit_click(event, $w) {
console.log("saving");
//Send a blank message to the HTML element. This tells the HTML
//element you want it to send you its contents
$w("#html1").postMessage(" ");
//Receive the message from the HTML element
$w("#html1").onMessage((event) => {
//Set the value for the rich text field of the dataset's
//current item to be the data in the HTML element
$w("#dataset2").setFieldValue("longDescription", event.data);
//Submit the current item of the dataset
$w("#dataset2").save()
.then((res) => {
console.log("saving", res);
$w("#PropertyInfo").value = null;
$w("#Location").selectedIndex = undefined;
$w("#Type").selectedIndex = undefined;
$w("#Guests").selectedIndex = undefined;
$w("#Bedrooms").selectedIndex = undefined;
$w("#Bathrooms").selectedIndex = undefined;
});
});
}
Awesome thank you I will give that a go. I meant adding fonts to the ck editor though so the client can enter them the same way and they will display correctly on my dynamic page?
That’s functionality that’s specific to the CKEditor that we happened to use in our example. You’d have to check out their resources to see if that’s possible and how.
Thank you Jeff, I will try check it out. Your code works great however as u mentioned it is set to read and write and needs to be only write but I have an issue, I have run into before where my dataset has disappeared and I can’t find it! Can you help at all?
Hey I tried this code but it didn’t. Can someone take a look at my code and let me know where the error is. The saved everything except the html information
Hey Nathan,
You’re missing a closing } at the end of the function and the parameters in the function declaration.
This should work:
export function button1_click(event, $w) {
//Send a blank message to the HTML element. This tells the HTML
//element you want it to send you its contents
$w("#html1").postMessage(" ");
//Receive the message from the HTML element
$w("#html1").onMessage((event) => {
//Set the value for the rich text field of the dataset's
//current item to be the data in the HTML element
$w("#dataset1").setFieldValue("itemDescription", event.data);
//Submit the current item of the dataset
$w("#dataset1").save();
});
}
Hi Jeff, Thank you so much for your work, you have been very helpful!
One more for me. I am basically creating a client portal so they can add, edit and delete the holiday properties themselves. I have the add form working great, and I will duplicate for the edit form as I have seen on the article about this.
However, from my main properties page I have repeaters listing all the properties and I wish to link an ‘edit property’ button to its own dynamic page with the form filled out to edit…Is this the way to do this? And if so how?! Thank you
The way to do what you want is exactly the way you described
Just create set up your dynamic page with the input elements for the fields in your properties collection. Connect them to the dynamic page dataset, but make sure to change the dataset to read-write. You’ll need a submit button also.
Now add a button to your repeater that links to that dynamic page and when a user clicks the button they will get to the dynamic page for the specific item that the repeater item was displaying. The input elements will display the current data in the collection. Your user can then edit the data there and submit it to update the collection.
Thank you Jeff. But I can’t work out what to call the dynamic page? I have one called property/title but not sure how to have one for the edit page? And how to link to dynamic page?
Site at tailoredwebdesign.wixsite.com/book-the-best
Any advice would be amazing!