Skip to main content

Creating a Property Editor With Umbraco 14

This is one of a series of posts looking at migrating Umbraco packages to Umbraco 14 and the new backoffice. Other posts in this series:

  1. Introduction
  2. Upgrading to Umbraco 14 Preview
  3. Creating a Property Editor With Umbraco 14
  4. Adding and Deleting Criteria

A "Hello World" Property Editor

The Umbraco documentation is a good guide for getting started, with details on creating an extension and creating a property editor.

Using the scripts provided I created an extension within a folder created in my main package project that I called client-src.

npm create vite@latest -- --template lit-ts personalisation-groups
cd personalisation-groups
npm install
npm install -D @umbraco-cms/backoffice@next

This sets up some files that make up an extension to the backoffice, using the latest preview release from the Umbraco prereleases feed.

Next step as described in the docs is to add a vite.config.ts file. I set mine up to export the built files rather than to the the default dist folder, to the /App_Plugins/PersonalisationGroups folder, which is where they will need to be for package distribution.

I then modifed the property editor element file to just display a message in the backoffice.

Finally, I added an umbraco-package.json file that registers the extension with the backoffice. The important parameters to set correctly are js, which needs to reference the compiled JavaScript entry point, and propertyEditorSchemaAlias, which needs to match the alias defined by the server-side property editor. This server-side component is much as it was in Umbraco 12, but there are some properties such as the "view" and "icon", that are now picked up from the client-side registration.

Having manually copied over the contents of the /App_Plugins/PersonalisationGroups to the equivalent location under the Umbraco 14 test site, I could restart it and view the results. Under Settings > Data Types, I could update my data type to reference the property editor that was now available in the dialog.

And viewing the content, the "hello world" message was rendered.

Migrating the Property Editor

To go beyond the most basic example it was time to start migrating over the functionality and presentation from the angularjs version of the property editor. Here you basically combine two files - the angularjs view and controller - into one, the implementation of UmbPropertyEditorExtensionElement. You can see my before and (work in progress) after if you follow the links in the previous sentence.

For the view, this can be copied into the render() function. Angularjs should can be removed. Instead, template string interpolation can be used to render properties from the class.

Functions from the controller can be moved into the element class, making use of Typescript enhancements to mark them with appropriate access modifiers (generally private, and following the convention of an underscore prefix). I'm still getting used to the static typing, but as a C# developer it's certainly welcome. Rather than working with raw JSON as was necessary previously with the property editor value, it's now possible to define and import types, and have compile time checks for correct usage when passing into functions.

Accessing External Data

Oftentimes a property editor needs to retrieve some data from Umbraco. Personalisation Groups needs to retrieve a list of criteria that are registered with the package, which is obtained via a server-side controller.

For Umbraco 12, I inject the $http angularjs service and use that to retrieve the data.

For Umbraco 14, we can use the native fetch method.

Replacing Angularjs Injectors with Dynamic Imports

In order that the personalisation package could be extensible, I have a feature where criteria can be registered and loaded at runtime. Part of the criteria implementation is a JavaScript function responsible for translating the raw data stored with the property editor to something more friendly to display to editors. For example, the "day of week" criteria translates an array of day numbers, e.g. "1, 3, 5", to a display value of "Monday, Wednesday, Friday".

In the Umbraco 12 implementation, this is a small angularjs service, which is pulled in at runtime using the $injector service.

With Umbraco 14, this becomes a vanilla JavaScript module, accessed using Typescript dynamic import statements.

Following a fair bit of trial and error my state of play is a partially functioning property editor, displaying the information held in the property data.

Next steps are to improve styling, using some of the Umbraco UI library elements. And also move on to the editing side of things - allowing new criteria to be added and existing ones edited via a right-hand panel dialog.

For more complicated packages, there's probably value in more structure than I have so far too. If you look at the core property editors, they all use nested components (see the slider property editor here for example). It may also be useful to introduce a service or resource class to wrap the data access responsibilities. It's probably not needed here, but it'll be something to look into for future work on larger projects.

To be continued... sometime...


Post a Comment