• Portretfoto van Ruben Hesselink
    Ruben Hesselink

External links in Wagtail Rich Text fields

Rich Text fields in Wagtail are widely used and popular due to their extensive functionality and expandability. However, there is one feature that is often missed: the ability to add links that open in a new tab. Until now.

For the past 6 months, I have been interning here at Four Digits, and one of my assignments was to develop a feature for the Rich Text fields in Wagtail that allows adding links that open in a new tab. In this blog post I am going to walk through how I achieved this.

To add a new feature to Rich Text fields in Wagtail you need to create a Wagtail hook to register the feature. In this Wagtail hook you declare a Label and Description for the feature:

control = {
        "type": type_,
        "label": "New tab 🔗",
        "description": "Open link in new tab",
    }
External link feature button for Rich Text
Label and description for the external link feature

In this hook you also how to register a draftail EntityFeature here you declare the label, description and custom JS and CSS if needed: (I won't dive into the JS and CSS because this is too large to explain in this blog post.)

features.register_editor_plugin(
    "draftail",
    feature_name,
    draftail_features.EntityFeature(control, js=["js/newtab.js"], css={"all": ["css/newtab_form.css"]}),
)

In this case I needed custom JS and CSS to render the form and handle form submission. This was done using React and DraftJS

Form for the external link feature
Form for the external link feature

The last thing that needs to be done is to handle the database format conversion. This done by registering a converter_rule:

features.register_converter_rule(
    "contentstate",
    feature_name,
    {
        "from_database_format": {"a[target='_blank']": NewTabLinkEntityElementHandler(type_)},
        "to_database_format": {"entity_decorators": {type_: new_tab_link_entity_decorator}},
    },
)

"from_database_format" and "to_database_format": These are key-value pairs specifying the conversion rules for the feature when converting from and to the database format.

"from_database_format" uses the NewTabLinkEntityElementHandler

class NewTabLinkEntityElementHandler(InlineEntityElementHandler):
    mutability = "MUTABLE"

    def get_attribute_data(self, attrs):
        """
        Override this method to add additional data to the entity.
        """
        return {
            "url": attrs["href"],
            "target": "_blank",
            "rel": "noopener noreferrer",
        }

This class overrides the get_attribute_data method to add additional attributes to the entity.

"to_database_format" use the new_tab_link_entity_decorator

def new_tab_link_entity_decorator(props):
    """
    Draft.js ContentState to database HTML.
    Converts the ``LINK`` entities into ``<a>`` tags with the right attributes.
    """
    return DOM.create_element(
        "a",
        {
            "href": props["url"],
            "target": "_blank",
            "rel": "noopener noreferrer",
        },
        props["children"],
    )

This function is responsible for converting Draft.js ContentState entities into HTML. It creates a new <a> element with the appropriate attributes

Submitted link
Submitted external link

With this we have now have registered a working external link feature.

We made this package open-source so it is available for usage in your own projects. To use this package go to the following link and follow the instructions: https://pypi.org/project/wagtail-external-link-richtext/#description

We love code

Cookies

Wij maken gebruik van cookies. Meer hierover lees je in onze Privacy- cookieverklaring.