Project

General

Profile

Actions

Renderer Refactoring » History » Revision 10

« Previous | Revision 10/11 (diff) | Next »
Philipp Gröbelbauer, 12.06.2024 12:29


Renderer Refactoring

Branch: https://git.math.uzh.ch/typo3/qfq/-/tree/F17252_Renderer_Refactoring

Motivation

To achieve a more modern look and feel, QFQ Forms should support Bootstrap 5 in addition to the previously used Bootstrap 3.
However, implementing this functionality into the current codebase while still practicing "clean code" is not possible.
Therefore the current code is being refactored to support future expansion.

Concept

Previously, preparation and rendering of the form with all its form elements was handled in AbstractBuildForm.php and BuildFormBootstrap.php.
The new concept introduces many new classes, making the code much more modular.
Most notably: Separating Configuration and Rendering of Form and FormElements !
By doing this, new Renderer Classes can be implemented in the future, which use the same AbstractFormElement objects to render the element in a different way (e.g. Bootstrap 5).

Class diagram

See the class diagram below:

Sequence Diagram Form and FormElement Instantiation

tbd

Sequence Diagram Rendering

The diagram below describes the rendering process.

  • The BaseRenderer (or any specific implementation of it) takes the previously instantiated Form object that describes all aspects of the form that is to be rendered.

Dev Guide

This section should answer common questions on how to use the refactored code and how to expand upon it.

Adding a New Form Element

This chapter describes how new form elements can be added into QFQ in the new model.
In this example we are assuming a new FormElement "Chat" should be implemented in QFQ.
Follow these steps:

Create a FormElement class

Create a new class ChatFormElement in the folder Core>Form>FormElement.
This class needs to extend AbstractFormElement and should call the parent's construct method when instantiated, as seen in the screenshot below.
If the form element you want to introduce is a ContainerFormElement, then extend ContainerFormElement instead of AbstractFormElement!

The job of this class is to prepare and process all data that is needed to display the element.
This class must not return any HTML or make assumptions about the way in which the element will be displayed! It exists completely outside of the choice of BS3/BS5/etc.

Preparation and processing of data can be done after calling parent::process.

Add the new class to FeFactory

Add a new CASE block to the SWITCH statement in FeFactory.php.
This way the factory will return an object of your newly created class when needed.
It is best to add a new constant in Constants.php that defines the new FE type. In this example the constant FE_TYPE_CHAT is simply defined as 'chat'.

Set up the BaseRenderer

Create a class ChatRenderer in the folder Core>Renderer>FormElement>Base.
It needs to extend the class FormElementRenderer.
This new class is supposed to render a chat element completely independent of the used CSS Framework.
In practice, this class might stay empty.

Next up, edit the file Core>Renderer>FormElement>BaseRenderer.php .

Add a new protected field "chatRenderer" of type ?FormElementRenderer to it.

In the constructor of BaseRenderer, instantiate an object ob your previously created ChatRenderer class and assign it to the new field.

In the SWITCH statement of the renderFormElement function, add a new CASE block for your new FE.
This ensures that the BaseRenderer will be using your ChatRenderer class to render objects of the type ChatFormElement.

Create Specific Renderers

The Chat Form Element will have the same look

Updated by Philipp Gröbelbauer 18 days ago · 10 revisions