A difference between using a headless CMS and a traditional one is that you do not have the same control over the editing experience of the editors since the actual editing interface is in the cloud and not on premise. Does that mean that we cannot give editors custom editor controls? A while back I posted a pretty in depth article on how to extend the EPiServer editing interface with a custom control for creating polls. It took quite a lot of pain and effort to get that working. I was curious how I could achieve the same thing using Contentful and read up a bit about it on their site. It turns out it isn’t that hard at all to create your own custom edit controls in Contentful!
A word of warning!
The UI extension API is still in development and likely to change over time. It is therefore not recommended to use for business critical solutions at this time.
There’s a whole section over at the Contenful site dedicated to UI extensions which is nice. What’s even better is that it’s all open source and can be found on GitHub. What really blew me away when browsing through the examples though was this: https://github.com/contentful/widget-sdk/tree/master/examples/chessboard
What!? There’s an example of an UI extension to show a chessboard! That is just beyond awesome. People that know me also know how much I love chess. If there’s one extension that every CMS needs it’s this one!
Anyway! Lets get on with our poll extension. To get started it is easiest to download and use the CLI tool provided by Contentful. You can find it on github here. You install it through NPM (if you do not have Node or NPM you can just go to nodejs.org and download and install). Simply run
npm install -g contentful-widget-cli. The global (-g) flag is to make sure the CLI is available to us globally on our machine.
Once we have the CLI tool installed we can run commands directly in our command prompt to create, read, update and delete UI extension widgets from Contentful. To do that we simply run
contentful-widget [command] [options] where command can be any of create/read/update/delete and options can be a number of options for each command separately. To list available options we can run each command with the
Before we get into creating the actual widget there’s one more thing to set up. When using the CLI it will need to authenticate with Contentful to make sure you are authorized to upload and modify widgets. This is done by creating an OAUTH authentication token and setting it in an environment variable. To obtain a token you simply login to contentful and generate one here. We then set the environment variable. I did it using powershell like this:
$env:CONTENTFUL_MANAGEMENT_ACCESS_TOKEN = "TOKEN"
For windows users the Contentful documentation is missing the bits of how to set up the environment variable, it simply tells you to run
export CONTENTFUL_MANAGEMENT_ACCESS_TOKEN = "TOKEN" which is not a command that exists in windows. However you could do it through powershell like I did or just add the environment variable manually.
Once these few steps are done it’s time to actually create our UI extension. It will consist of only two files. Yes, you read that right… two files, and one of them is just a config widget.json file that looks like this.
This little guy simply tells Contentful the Id of our widget, which is to identify it internally. The name, which is the name that will show up in the Contenful GUI like this:
Then we’ve got the srcdoc which is the actual document that will present our widget in the Contentful GUI. And finally we have an array of fieldtypes which is the type (or types) that our widget will use internally to store its data.
So that’s the configuration and then we have the actual widget, which is just a plain old html file.
A couple of interesting things here. Firstly there’s a widget-css that we can reference to make sure our widget keeps the look and feel of the Contenful GUI. There’s a fairly rudimentary style guide that you can use to view the most basic controls and classes. Then we reference the widget client library which contains the API for communicating with the contentful back end. We also reference jquery. Lastly comes the actual HTML which is very rudimentary, a textbox for the title of the poll and a textbox for the first question. The interesting stuff comes in the scripts part, here’s what it looks like:
I first started out using
blur instead of
input as the event that would trigger the saving, but that turned out to be a mistake. Blur triggers when you leave an input field which sounded kind of ideal at first to minimize the number of saves triggered, but created an interesting problem. If the user changed something in the heading input field for example and then immediately clicked the publish button it would result in this error:
What happened here is that my click event on the publish button actually registered before my blur event on the input field. If I clicked on the publish button again it saved nicely, but that’s obviously not an acceptable user experience, which is why I changed it to input events instead.
Here’s what the final property looks like in the Contentful UI, also including the slug and documents properties for comparison:
This very simple example only scratched the surface of what you can do with the UI extensions in Contentful. The widget object for example can be used to get a reference to the entire entry that’s being edited and can modify or read any field. This means we can easily build inter-dependent widgets that listen to changes of each others values and update accordingly. I’m looking forward to playing around some more with the api in the upcoming weeks and see what else you can create.