Breaking change to the Rich Text editor in Umbraco 13

You are probably not aware of the breaking change related to the Rich Text editor introduced in Umbraco 13.

Introduction to the Breaking Change

A breaking change has been introduced in Umbraco 13, which you should definitely take into account when upgrading from the previous version.

The Rich Text editor is probably the most common editor used in each Umbaco project. Therefore, you need to be aware of it when upgrading your existing Umbraco website from older versions.

Rich Text Editor in Umbraco Example

Rich Text Editor in Umbraco Example

Unfortunately, you will not find clear or direct information about this breaking change on the v13 landing page:

https://our.umbraco.com/download/releases/1300

or when comparing latest v12 version to the 13.0.0:

https://our.umbraco.com/download/releases/compare?from=12.3.10&to=13.0.0

Understanding the New Rich Text Editor Format

You'll have to dig a little bit deeper to find it. Basically, the breaking change I will try to explain is related to the new feature. I mean the possibility of including blocks in the Rich Text Editor introduced by another pull request as below:

While this PR does not break anything on the server side (the new RTE format is backward compatible with the old one), it will break custom views in the back office. The new RTE format is an object that contains the markup string as a markup property, whereas the old format is "just" the markup string. When using an RTE property in a custom view without adapting to the new format, one will experience views that state "[object Object]" instead of the markup string.

When you decide to scroll down the conversation in this PR, you will notice that the Rich Text properties have updated format as below: 

{
   "markup":"<p>Text from the RTE</p>",
   "blocks":{
      "layout":null,
      "contentData":[
      ],
      "settingsData":[
      ]
   }
}

Of course, you needn't worry about the new format if you are not manipulating the values of the Rich Text properties through the ContentService.

If you are parsing, validating, or performing any custom operation on the values of the Rich Text editor properties, you will not find how to deal with those properties in the documentation of the Rich Text editor. I have no doubt this will be documented shortly.

For now, we decided to explain to you the new format of the Rich Text property value in this article.

Exploring the Umbraco Source Code

We reviewed the latest definition of the Rich Text property editor. I mean the RichTextPropertyEditor class as below:

/// <summary>
///     Represents a rich text property editor.
/// </summary>
[DataEditor(
    Constants.PropertyEditors.Aliases.RichText,
    ValueType = ValueTypes.Text,
    ValueEditorIsReusable = true)]
public class RichTextPropertyEditor : DataEditor
{
    private readonly IIOHelper _ioHelper;
    private readonly IRichTextPropertyIndexValueFactory _richTextPropertyIndexValueFactory;

    /// <summary>
    ///     The constructor will setup the property editor based on the attribute if one is found.
    /// </summary>
    public RichTextPropertyEditor(
        IDataValueEditorFactory dataValueEditorFactory,
        IIOHelper ioHelper,
        IRichTextPropertyIndexValueFactory richTextPropertyIndexValueFactory)
        : base(dataValueEditorFactory)
    {
        _ioHelper = ioHelper;
        _richTextPropertyIndexValueFactory = richTextPropertyIndexValueFactory;
        SupportsReadOnly = true;
    }
...
}

We noticed shortly that the RichTextEditorValue model was introduced as follows:

[DataContract]
public class RichTextEditorValue
{
    [DataMember(Name = "markup")]
    public required string Markup { get; set; }

    [DataMember(Name = "blocks")]
    public required RichTextBlockValue? Blocks { get; set; }
}

How to Handle Rich Text Property Values

Happily, additional helpful RichTextPropertyEditorHelper has been implemented as well.

The RichTextPropertyEditorHelper contains two useful methods. The first one allows to parse string value into the RichTextEditorValue model.

The second method allows to deserialize any instance of the RichTextEditorValue to string - JSON value.

We concluded that the RichTextPropertyEditorHelper should be used whenever we try to handle any Rich Text property value. This way, we don't need to worry about unexpected format.

It's worth noting that the TryParseRichTextEditorValue method detects whether the serialized value is a JSON or plain TinyMCE markup, which is well-known from previous Umbraco versions. Therefore, you don't need to worry about the format of the value you are passing to this method.

After reviewing the implementation of the TryParseRichTextEditorValueI decided to check one more thing. You probably know what I mean. Yes, I decided to look at the existing Rich Text property values stored in the database.

I noticed nothing has changed, so there is no migration plan for the existing values. Please judge for yourself whether this is good or bad :)

Yes, I know it might take a while to update existing values when upgrading to v13, but maybe it would be better not to store mixed property values in the database.

Conclusion

We noticed that available methods require IJsonSerializer as a parameter.

Therefore, we recommend creating a custom helper and injecting IJsonSerializer into it, especially the TryParseRichTextEditorValue method, which requires ILogger as well.

This way, it will be much easier to handle any Rich Text property value.

Additional notes

I'm wondering how the Rich Text property values are handled during indexing in the Examine, but this is a different story. We will try to keep you updated.

Please be aware of the mixed format of the Rich Text property values, especially when you are playing with values directly in the Umbraco database.

What's Next?

Explore our blog for more insights, and feel free to reach out for any queries or discussions related to Umbraco development.

↑ Top ↑