Build a custom renderer that uses the page editor

Overview

Sitefinity allows you to build your own custom renderer that can work with the layout service and the new ASP.NET Core page editor. This way, you can take advantage of a simplified, user-friendly way of building web pages and interactive frontend. 
For more information, see Layout service API.

The process of building your custom renderer requires the following main steps:

  • Consume the layout and content services on the frontend.
  • Integrate your renderer with the new page editor editor in the administrative UI.
    For more information, see The new Page editor.

EXAMPLE: This article demonstrates the concepts using examples from the Angular standalone renderer sample in Sitefinity GitHub repository.
In addition, you can also refer to the React standalone renderer sample.

Consume the layout and content services on the frontend

You can build the renderer with any client-side JavaScript framework or with any server-side framework.
The flow to render a page is the following:

Call the layout service

When a page is requested, the renderer must call the layout service for the requested page. 
For more information, see the app.component file of the Angular standalone renderer sample.

The call to the layout service looks like this:
/api/default/pages/Default.Model(url=@param)?@param=’home’

Where api/default is the URL of the service and home is the relative URL of the currently opened page. 

Response of the layout service

The response from the service is in JSON format.
For more information, see the service-response file of the Angular standalone renderer sample.

The response has the following properties:

  • The ComponentContext property is a ready-to-use, ordered, hierarchical tree of the widgets.
    This tree corresponds to the prebuilt layout of widgets that each page consists of and defines their order.
  • The SiteId and the Culture parameters are populated with the respective values for the current page.
  • The Scripts property contains scripts from Sitefinity CMS, such as personalization or tracking.

Render the widgets

After receiving the layout, the renderer iterates the hierarchical tree of widgets and renders them in the specified order.
For more information, see the component-wrapper.directive file of the Angular standalone renderer sample.

The rendering of each widget depends on the specific widget implementation that you have implemented. The logic behind the implementation is defined by the set of properties, provided in the layout service response for this widget.

Integrate the renderer in the backend UI

The backend interface provides an ASP.NET Core page editor that you use to build and edit the layout of ASP.NET Core pages. This page builder renders the content of the page inside an <iframe> element to enable isolation and better WYSIWYG experience.

To integrate your custom renderer with the page editor interface, there are several requirements. You need to first implement a working renderer that can render widgets and pages following the steps above. Afterwards, perform the following:

Open the renderer in the page editor

When you open the page editor, it automatically loads the frontend URL of the page in an <iframe> element, which provides isolation. Additionally, the URL, which the <iframe> element is opened with, contains the current domain name.

For example, if you have browsed your Sitefinity website with https://www.mycustomdomain.com and the URL of your page is /home, then the URL of the <iframe> would be: https://www.mycustomdomain.com/home?sfaction=edit.

The sfaction query parameter is used as a marker to inform the current renderer that the page is being opened for editing. This triggers the renderer to enter editing mode and to apply additional modifications to the HTML of the page, so that the rendered page is interactive with the page editor.
For more information, see the app.component file of the Angular standalone renderer sample.

Load the HTML content

Next, the page editor attempt to load the iframe HTML content. It  looks for the follwing:

  • Container tags
    Container tags are used as a starting point where widgets are placed – for example, the <body> element or the <div> elements of the <body> element. These container tags must be decorated with the data-sfcontainer attribute. 

    NOTE: If you need a user-friendly name for your placeholders during page editing, you can assign a value to the above attribute in the following way: <div data-sfcontainer=Root></div>, where Root is the label that will appear in the editor.

  • A JavaScript object for communication
    To help you implement your custom logic for inserting widgets, the page editor exposes several integration points. You control this process by defining a custom JavaScript object that you must place on the window object. This JavaScript object holds the following methods that communicate between the renderer and the page editor.
    • getWidgets
      Use this method to retrieve the widgets from the renderer. Each renderer may have different sets of widgets. These widgets are displayed in the widget selector where users can pick them.
    • getWidgetMetadata
      Use this method to retrieve the metadata of the widget. The metadata defines the properties of the widget, so that the page editor can dynamically build the widget editing UI.
    • getCategories
      Use this method to retrieve the categories that are used to group the widgets in the widget selector.
      The Layout category is mandatory and you must always return it in the result.
    • renderWidget
      Use this method is when a widget is inserted in the page during design time. The expected return result of the method is either plain HTML decorated with a set of attributes, or a pre-built element with its attributes defined. The element is then processed and appended to the DOM.
  • An event that fires when the renderer is ready

All the these changes to the rendered page must be made only during page editing - the sfaction parameter must be used for this conditional logic. Otherwise, the HTML and JavaScript changes will pollute the frontend.

Host the renderer

The easiest way to host your custom renderer would be to host it in a special folder, inside Sitefinity CMS.
For more information, see the Angular standalone renderer sample » Deployment. Hosting the output files on that place enables the renderer to be integrated with the new page editor.


Increase your Sitefinity skills by signing up for our free trainings. Get Sitefinity-certified at Progress Education Community to boost your credentials.

Web Security for Sitefinity Administrators

The free standalone Web Security lesson teaches administrators how to protect your websites and Sitefinity instance from external threats. Learn to configure HTTPS, SSL, allow lists for trusted sites, and cookie security, among others.

Foundations of Sitefinity ASP.NET Core Development

The free on-demand video course teaches developers how to use Sitefinity .NET Core and leverage its decoupled architecture and new way of coding against the platform.

Was this article helpful?

Next article

ASP.NET Core samples