Custom renderers
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.