Creating Content as Reusable Modules

Creating Content as Reusable Modules

Having to maintain a lot of duplicate content can be cumbersome. If, for example, you have a block of content consisting of the same text and download button on a dozen or more landing pages, you don’t want to touch each and every one when the text or the button’s link needs to be changed. Handling multiple instances of the same content in this way is not only error prone but also tiresome.

In this tutorial, we will show you how to create and maintain “global content”, with “global” referring to a Scrivito-based website as a whole. We will create a CMS object class for content of any kind, and a widget class for placing this content anywhere on any page. This combined will allow editors to reuse parts of pages wherever they wish. Changes can be made in place and cause all other instances of the same content to be automatically changed as well. We will be calling such an assembly of reusable content pieces a “content module” or just a “module”.

Sounds great? Let’s begin.

The “ContentModule” object class

The Scrivito Example App, on which this tutorial is based, already includes object types for maintaining content meant to be used anywhere on the website, Author, Event and Job. Instances of them can be rendered either as individual pages – because they have a component associated with them –, but also in overviews where only a subset of their attributes is used.

Our ContentModule instances, in contrast, never need to show up as pages; their only purpose is to hold content pieces together so that they can be used again and again on various pages. For this reason, we don’t require a component that renders the instances but just an object class and an editing configuration for creating them.

The object class

Our object class provides ContentModule instances with two attributes, title and content. The former lets us make a module’s purpose clear to editors when working with it. The latter is a widgetlist for freely putting the module’s content together:

Notice that the widgetlist we are providing is restricted to a few basic widget types so as to prevent editors from building “monster modules” made up of containers such as columns and boxes, etc. The possibility to add containers to a module would also bear the risk of putting a module into a module of the same type, which could cause them to not work anymore.

The editing configuration

The ContentModule’s editing configuration is the smallest ever. There’s no need to add a title or description to the title and content attributes here as their names are self-explanatory. The only place where the ContentModule’s properties show up is the Content Browser.

Making content modules known to the Content Browser

Since the Content Browser is the place where Content Modules can be defined or deleted, let’s extend its configuration accordingly. Just add the lines given below to the return value of the defaultFilters function and the FILTER_PRESENTATIONS constant:

Using the Content Browser, you could now start creating content modules and even give them a title or add widgets to their content.

However, at this point, you cannot place content modules onto pages and edit them there, so let’s build a widget for that.

The “ContentModuleWidget” class

Our widget’s purpose is to enable editors to place content modules onto pages. For this, the widget requires just a single attribute, one for specifying the module to use. Typically, attributes pointing to objects are of the reference type, so here we go:

We named our attribute module, and we want it to point only to an object of the ContentModule type. This restriction comes into effect when the module attribute is edited and the Content Browser then opens to let the editor select the attribute’s target object.

The widget’s editing configuration

The editing configuration of our ContentModuleWidget simply makes the module attribute editable on the properties view of widget instances and adds a title and a description to it.

By the way, the titleForContent key defines the tooltip text displayed for instances of the widget when hovering over their handle.

The widget’s component

The main task of the ContentModuleWidget’s component is to look at its module attribute and, if set, render the content attribute of the ContentModule object it points to.

Depending on whether Scrivito’s editing interface is in editing mode and a module is present, a hint either about the consequences of changing the content, or on how to specify the module is displayed.

All of a sudden, we’re done! If you already have a ContentModule object, you can now add one or more ContentModuleWidgets to a page, specify the ContentModule to use (via the properties), and add content to it, directly on the page.

Final words

Being able to change recurring content simply by touching any of its occurrences is definitely of great help to editors. It obviates the need to recall where this content has been included as well and to then repeat the adjustments there too, which saves a lot of time and makes it really easy to overhaul specific pieces of content.

If most or all of your content modules are made up of roughly the same widgets, you could even go one step further and predefine the widgets a new module should be equipped with. See Creating a Custom Page Type for instructions on how to specify an object’s initial content.

Note that our approach to providing global content has a small catch: Pages where the search term occurs only in content modules do not show up in the search results. To remedy this, the modules containing the search term would have to be determined with another search query, and the pages referencing the found modules would then have to be added to the original search result.