Extending Custom Elements

Extending Kentico Cloud with Custom Elements

When modeling content, you frequently stumble upon the need of storing data in specific structures that go beyond conventional types like string, number or list of options. Typical examples are countries and states. You can not use a free text field for this unless you fancy giving editors free rein. So how can you extend the system and store such data?

Ondrej PolesnyPublished on Mar 26, 2019

Why should you not use a free text field? Apart from the fact that editors would have to write country names every time, you would end up with a pile of unstructured data, many duplicates, and typos. Because not all countries in the world have states, you also need a bit of business logic in the selector. Therefore, a simple dropdown would not be an ideal solution either.

Custom Elements

First of all, I want to emphasize that the word custom does not mean you need to implement it. You don't even have to download, compile, or install it. No, to use a custom element within Kentico Cloud, you only need to copy and paste its URL. But I'll get to that later. First, let me explain what a custom element is.

A custom element is a standalone web application - a website - that is hosted somewhere on the internet. It's not implemented within Kentico Cloud but integrated into the UI using iframes. Therefore, it can sit on a server far far away (preferably not too far though - latency still applies). Kentico Cloud will communicate with the custom element in an iframe via JavaScript, provide it with initialization data and listen for data changes to make sure they are persisted. The custom element is in charge of the rest. The way it displays the data, processes them, transforms them and serves them back to Kentico Cloud is orchestrated within its implementation.

Country and State Selector

So what would that country and state selector look like? It is an empty page with two dropdown selectors. The second dropdown showing states is displayed if the selected country has any states. It does not persist any changes yet, because there is no parent window to communicate with (Kentico Cloud).

If you are interested in using an existing custom element, feel free to jump to `Using a Custom Element section`.

Building a Custom Element

The country and state selector covers a use case of country-related content items. It could be your company's offices, your country's embassies or trips of your favorite travel agency. All these items are related to a specific country/state.

You see, when your data structure goes beyond standard data types, you may need a custom element. The best place to look for one is our GitHub repository. If you can't find one matching your requirements, you're lucky! You get to enjoy all the fun of building one :-), so just follow my story of country and states selector.

How Do I Start?

Every custom element is a standalone application, so it's up to you to choose your favorite platform. However, the communication with Kentico Cloud happens via JavaScript, so an implementation based on Node.js or your favorite JavaScript framework will work best.

While you can start on a green field with just Notepad, we prepared a DevKit for you to speed up less interesting tasks like minimizing assets, including Kentico Cloud styles and so on. The DevKit is available on GitHub, and you can start by cloning its repository:

git clone

And installing missing node modules:

npm install

To create a new custom element, navigate to the `/client/custom-elements` folder and create a new folder for it. You will also need to create two files:

  • index.pug
    The view of your custom element in Pug.
  • code.tsx
    The JavaScript code file with custom element logic.

Note that the JS file has a TypeScript extension so you can use TS if you are more familiar with it, but you can also stick to standard JavaScript code. The file should be named after your custom element—in my case, it's selector.tsx.

Which Framework Should I Use?

The devkit works with any JS framework, so feel free to use your favorite one or plain JS. These days I work with React.js a lot, so I decided to use that. I needed to install two additional packages at the devkit root:

npm install react react-dom --save

How Does a Custom Element Communicate with Kentico Cloud?

Every component, even if it is just a simple text field, needs to communicate with Kentico Cloud. They need to exchange data when a content item is opened or updated to make sure editors see the right values and their work is persisted. The component also needs to prevent updates to already published content items and tell Kentico Cloud how much room it needs to render correctly.

The Kentico Cloud Custom Elements API provides methods for all these cases. Take a look at my (simplified) implementation of the country selector in code.tsx:

CustomElement.init((element, _context) => {
  const data = element.value ? JSON.parse(element.value) : null;
  const components = (
    <CountrySelector data={data} disabled={element.disabled} customElementApi={CustomElement} />
  ReactDom.render(components, document.querySelector('#reactapp'));

Kentico Cloud initiates the custom element by invoking CustomElement.Init and by providing all data within element and _context objects. I used that event to initialize my component with data (element.value) and flag describing whether the component should allow editors to change values (element.disabled).

My selector uses two data fields - countryCode and stateCode - to persist the editor's selection. The element.value object will, therefore, be null (no value or brand new content item) or look like this:

{countryCode: "US", stateCode: "NH"}

The last parameter (customElementApi) enables my React component to call method setValue() of Custom Element API that persists data in Kentico Cloud. My selector invokes it every time a user changes a country or state to make sure his or her choice is persisted.

As the selector currently uses the same height for all use-cases, it is set to 250px using method setHeight().

For the full list of available methods check out the API reference in Kentico Cloud documentation.

Building and Deploying Custom Elements

When you are finished with the implementation, you should first reward yourself with a beer or two. After that, it's time to build and deploy it for the whole world to see. The first step towards that is to build the custom element:

npm start -- -cjsm

These flags ensure that the custom element will be compiled, styles and JavaScript minified and inlined within a single HTML file. Once the process completes, take a look in \built\custom-elements\{element name}. You should see two files there - index.html and font file (woff) with Kentico icons.

As the custom element is represented by a single HTML file, you can host it pretty much everywhere (Heroku, Surge, your hosting space, etc.). However, I decided to host it on GitHub in the Kentico Custom Element Samples repository as it already hosts a few custom elements and it is the best place to share it with other developers. This way anyone can find my selector quickly and use it within their projects. The repository is also using GitHub pages, so all elements hosted there can be directly referenced using URL.

Using a Custom Element

So the custom element is deployed and accessible online (we have its URL). Cool, that was the hard part. Now let's use that custom element in Kentico Cloud.

Using a custom element in Kentico Cloud

When you open a content type definition, you can drag&drop the generic Custom element to the list of fields. In the configuration of your new field, there is a textbox for the custom element URL. As my country and state selector is hosted on GitHub, the URL looks like this:

Note that custom elements always need to be accessible via HTTPS to ensure secure communication between Kentico Cloud and the custom element.

Country and State selector in Kentico Cloud

That's it. No other steps needed. Go ahead and open any content item based on the updated content type and try it out.

The same way you can also leverage any custom element from our daily growing list and please your editors with a great user experience when dealing with specific data structures.

Get $150 for Your Custom Element

Country and state selection are pretty common when working with content. So would it make sense for every developer to create their own custom selector for it? Probably not. As I already created one it's easy for everyone else to use it - just reference its URL within custom element configuration.

We love it when developers help each other and sharing custom elements would save your fellow developers tons of time. And we also like to play. That's why we organized a contest during March 2019 that rewards custom element contributors. The rules are simple - create a custom element and contribute it to our samples repository on GitHub. We will reward the top 10 best custom elements with a $150 Amazon voucher! That gets you an Amazon Echo, Apple Pencil or 20x USB cables for your phone (that gets my USB cable consumption covered for a year)! 

To find out more and enter, visit

*UPDATE: The contest deadline has been pushed to April 14th*

Written by

Ondrej Polesny

As Developer Evangelist, I specialize in the impossible. When something is too complicated, requires too much effort, or is just simply not possible, just give me a few days and we will see :).

More articles from Ondrej