Published on October 9, 2017
Editor's note: UI Extensions are now even more powerful! Learn about the App Framework.
Did you know that there’s an easy way to extend the Contentful UI? This blog post will show you how simple it is to create custom UI extensions.
Building a product that everyone likes is hard. This is especially true in the world of content management—and that’s mainly because different content types require different types of interfaces to look their best.
While we work hard to provide you with the best UI possible, we don’t always know what your use cases are. This is where UI extensions come into play.
This blog post will show you will show you how to customize the Contentful web application with custom UI elements using the UI extensions SDK. This will allow you to build interfaces that editors want to use and that are adapted to your organization's needs.
Custom UI extensions work thanks to the Contentful's UI extensions feature. This feature enables you to upload HTML files to Contentful which will be displayed in an iframe
inside of the web application.
You can then use the UI extensions SDK within the iframe
to communicate with the surrounding web application. The SDK has all of the functionality you need to build rich interfaces.
And to make your custom UI components blend in correctly, so that you don’t annoy people with visual inconsistencies, you can include a stylesheet that gives you the Contentful base styling.
Then you have to define a file called extension.json
which includes the configuration for your UI extension inside of the Contentful web app.
Things like querying other APIs for autocompletions with third-party services is painless. You can also tweak the web interface as needed.
UI-Extensions are plain HTML files—you can build whatever you want with them. And that's what I regularly do.
Part of my job is attending events, and I list the events I attend on my personal website. The underlying event content model is simple: it includes fields for a date, title, city, and country.
These fields make up the base for the event listing on my site, which is also configured to include the given country’s flag.
The flags are emojis and they require a country code to render. My problem was that I didn’t always know the country code of where I was going to—plus having to google it every time annoyed me. It wasn’t a good user experience.
All I needed was a simple select field that maps a readable country to the given country code. This is a perfect use case for a simple UI extension tailored to my use case.
So let's have a look at the UI extension code it takes to create what we want—starting with the configuration file:
I only want to store a letter combination, so a text value does the job. To make this UI extension available for text fields, I have to define Symbol
in the fieldTypes
property. You can find a list of all the field types in our documentation.
The key part of the code above is the custom select HTML element, which I found somewhere online. It maps the country codes to country names.
You just need to sprinkle some JavaScript on top of it to send and save the changes to the application.
If you need a country select feature for your next project, head over to the GitHub repository and you will find the installation instructions there.
A while ago at one of our Berlin User Meetups, a woman came up to me and we started chatting about how she uses Contentful. She talked about a few workarounds that her and her colleagues have to do when they work with tabular data. Because her company publishes articles that include statistics, this meant that they had to copy a lot of tables back and forth.
She said that the tables themselves were not complex—however, the field types provided by Contentful just did not fit their needs.
She didn't know about UI extensions, though. So, how could you implement an editable table in Contentful? Let's have a look.
First thing is to set up a different configuration file:
This file is fairly similar to the first example, but there is a crucial difference. That difference is that the UI extension should be available for the field types of Object
. Here Object
means that I can store any valid JSON object in Contentful.
When you think about it, this implies that you have the freedom to build the interfaces you need. You can define the data structure, and you can also define how this data structure should be edited. Cool, right?
In this case, I decided to go with an object that includes a tableData
property. This way it stays extensible and future-proof since we might want to add more items to this field later on.
The table itself is a two-dimensional array that includes the table header as the first entry.
The editor interface should then display this data in an editable table. And the code to do that looks like so:
Here’s what is going on:
The UI extension gets initialized.
The current field value from the Contentful web app is retrieved.
If there is no data stored yet, the data structure will be created.
The DOM table structure is built (by inserting tr
and td
into the table
element).
A global event listener is added to save new values on blur
.
Another cool aspect is that the UI extensions are encapsulated. That guarantees that you don't have to worry about clashing with other scripts or functionality. You provide the markup, you define the functionality with JavaScript and you don't have to deal with additional complexity. That's it!
If you want to play around with this example yourself, you can find it on GitHub.
The reference feature is my personal favorite because it allows me to build entire content trees and fetch them with a single request.
For me, the provided reference editor gets the job done. But for other use cases I understand that the interface can be improved—particularly to give authors a more natural and quicker solution for setting references.
Dave Olsen had the same thought. He asked me if it is possible to build a different reference editor that offers a quick select. The answer: It sure is.
Some more context: he’s dealing with an educational system and in his content model, he wants to create a quick reference to a particular college institution. Here’s what is needed to build just that:
Fetch all the entries of a specific content type.
Render radio boxes for the fetched entries.
Check the one that represents the currently saved value.
Save a new value in case another radio box is checked.
Let’s break this down step by step:
Note that the fieldTypes
only includes "Entry"
because this UI extension should only be available for reference fields.
I could hard code all of the content types that I want to show entries for, but there’s a more dynamic way to do it. When setting up a reference field, it's possible to define validations to only allow certain content types.
With the information about the allowed content types — I don't have to hardcode anything.
The init
function of a UI-Extension executes with an extension
object. This object also holds information about the current active validations (extension.field.validations
).
There can be several included validation types like for example the required
validation. Validations for a particular content type include the linkContentType
property, so that I can check for this property in order to figure out the validation type, and then concatenate all of the allowed content types later on.
The next thing is to fetch the entries for these content types. As the content types are already stored in an Array, you can map the content types to actual request promises and wrap them with a Promise.all
to retrieve entries of several content types at once but how do you make requests in a UI-Extensions. It turns out that the handed in extension
object includes a space
property which provides a getEntries
function.
After that, all the entries are available in the items
array.
The next step is to render the UI for these items. Firstly: it's important to know if there is already a field reference value stored. If that's the case then one of the radios has to have an active state.
The last thing is to react to changes and save the new values. To do that I queried all the radio elements and attached change
event listeners to them.
If one of them changes its value, this value is sent to the surrounding web app and then saved using the extension.field.setValue
method.
With this extension, I now can quickly select references with just one click. The example you see below shows a way to swiftly select authors for the blog content model that is included in the interactive getting started guide.
And since this UI-Extension is built in a general way it will work with any content model. Maybe you want to play around with it too?
Productivity in the digital world depends on the tools you use. The Contentful web interface simply can't address all your needs out of the box—but by using UI-Extensions you can customize the Contentful web app suite to fit you and your editors needs perfectly.
Because if the editorial workflow is too complicated, or could be done in a single step instead of two, go ahead and improve the interface—people will thank you for that.
Subscribe for updates
Build better digital experiences with Contentful updates direct to your inbox.