I'm a big fan of the native implementation, but it's limited when it comes to simple features such as cell merging and applying styles.
After some initial investigation into extending this block or attempting another implementation, we landed on using a customised TinyMCE rich text editor, with most of the controls stripped out to keep the editor tightly focused on table creation and editing.
This post is a simplified version of the docs that I wrote up to support the block.
Hopefully it will help someone wanting to do something similar, or more likely, it will remind my future, older, self how clever younger me was.
This block utilises the TinyMCE rich text editor to allow more control over formatting, cell merging, and cell alignment than the standard Wagtail
Rich text editor basics
A rich text editor in a CMS has to perform a number of functions to enable a consistent editing experience, and protect the data and front end visitors from badly formatted or malicious content.
In general, these steps are:
- Process the entered data to a format that can be saved to the database. The format will generally be HTML, but can involve manipulating items such as links to reference internal page ids (which is what Wagtail does). This is handled at the Python/Wagtail layer
- Upon loading a page editor, retrieve the stored HTML in the database, and process it to a format that the rich text editor can process and display for editing
- Upon loading a front end page, the stored HTML in the database will be retrieved and processed again to be in a format that is correct for template render. For instance, this would involve transforming internal page id references in links to native HTML links. This is generally done by use of the Wagtail
There are three key parts to this component, all should be taken into account if extending or amending how the component behaves or what its allowed inputs and outputs are.
By default, the HTML
<table> element and child elements are stripped from content stored in a Wagtail RichTextBlock. To enable these elements to be stored to the database, the Wagtail hook
register_rich_text_features is used to register these features and whitelist the allowed elements, and their allowed attributes.
TinyMCERichTextArea is subclassed to allow configuration and customisation of HTML handling.
We then override the
getDefaultArgs method to perform the following configuration:
- Configure the editor interface to restrict editing options to tables, pre-defined custom styles, bold text, and cell alignment
- Remove advanced table and cell property controls
- Inject a custom style sheet into the editor iframe to enable visualisation of custom styles
__init__ method adds the whitelister rules that were previously defined via the
We also override the
value_from_datadict method to use a helper method -
clean_data_for_db - to perform custom cleaning of the HTML data that is saved to the database.
AdvancedTableBlock defines a standard Wagtail
RichTextBlock with the argument
This block will then use the custom rich text field editor as defined in the settings for the Wagtail app.
get_context method on the
AdvancedTableBlock passes the database content to another helper method -
get_nodes_for_block - the template then loops through this list and outputs each table node.
The helpers for this block contains functions that do the following:
get_style_formatscreates a list of styles based on the pre-defined colour choices. These formats are then available to be applied in the editor, and are used in the final rendered HTML
get_allowed_attrsreturns a duplicated list of allowed attributes on all whitelisted table elements, for use in db and block HTML cleaning
clean_data_for_dbparses HTML from the rich text editor and:
- removes any disallowed root nodes (only
tableelements are allowed)
- removes any disallowed classes
- removes any disallowed style properties
- removes any disallowed root nodes (only
get_nodes_for_blockparses HTML from the database and:
- remove any disallowed style properties
- splits tables nodes into a list
Supporting CSS for the admin editor and front end templates is defined in an SCSS module using the base class
Give me the code!
Here's a Wagtail 2.15.x compatible Github gist containing all the required code and implementation notes.