v 1.8.73

Custom Render ― Question Elements

Sections in this topic:

API to use:
Event:
SurveyPDF.onRenderQuestion
Event parameter's popular options:
options.question
options.bricks
PdfBrick.unfold()
PdfBrick.textColor

Handle event ― onRenderQuestion

When exporting a survey to a PDF file, you can handle the SurveyPDF object's onRenderQuestion event to access and customize structural elements of any rendered survey question.

The event signature is as follows.

onRenderQuestion: EventAsync<(survey: SurveyPDF, options: AdornersOptions) => any, any>

Two parameters are passed to event handlers:

  • survey ― The event sender. A SurveyPDF object instance,
  • options ― An AdornerOptions object that contains the processed question's render information.

View the event sources: declaration, invocation.

See also:
SurveyPDF.onRenderPage (docs, sources)
SurveyPDF.onRenderPanel (docs, sources)

Use event parameter options ― AdornerOptions object

An AdornerOptions object instance is passed to onRenderQuestion event handlers as the options parameter. This parameter exposes the following set of properties to help you access and customize the rendered question's composite elements.

  • question
    question: IQuestion;
    Identifies the rendered question.

  • bricks
    bricks: IPdfBrick[];
    An array of PdfBrick objects representing the question's render structure.

  • point
    point: IPoint;

  • controller
    controller: DocController;

  • repository
    repository: FlatRepository;

  • module
    module: any;

Bricks

Within the PDF file content, question elements are represented by bricks (PdfBrick instances). Bricks are the most fundamental elements that are used to construct a document.

A brick is a simple element with a specified size, contents and location that is used to display any textual and/or graphic information on a document page. A PdfBrick object exposes the following API.

Position and size options:

  • xLeft
  • xRight
  • yTop
  • yBot
  • width
  • height
  • isPageBreak

Appearance options:

  • textColor
  • formBorderColor
  • fontSize

Methods:

  • unfold()
  • render()

Note:
If you just need to modify a brick's appearance, the simplest way is to use any of the appearance options, such as the text color (textColor) or font size (fontSize).

When working with bricks, the main challenges facing you as a developer are as follows:

  • understand the structure of bricks that compose a survey question being currently rendered into a PDF file,
  • access certain bricks that relate to the required question structural element (such as a question title, question description or an individual choice).

Our documentation does not currently provide detail information about the precise brick structure used to render survey questions of different types. We consider the rendering process to be an internal logic which might change in future releases.
However, we have an open suggestion issue - #49 - which you can track and add to if you feel a need for such a description and you can provide illustrative use cases of question element customization required.

It appears that the fastest way to understand how a question is rendered within a PDF file is to insert the debugger statement into an onRenderQuestion event handler and to investigate the rendered question's structure in a browser's DevTools Console.

surveyPDF
    .onRenderQuestion
    .add(function (survey, options) {
        debugger;
        // Your customization logic here...
        /*
        const plainBricks = options
            .bricks[0]
            .unfold();
        */        
    });

How to customize question titles

The code below shows how to handle the onRenderQuestion event to change question title colors (to highlight correct and incorrect answers) for questions of the Radiogroup type.
To modify the text color of title bricks, a brick's textColor property is used.

surveyPDF
    .onRenderQuestion
    .add(function (survey, options) {
        //debugger // <-- Discover the brick structure in DevTools        
        const plainBricks = options.bricks[0].unfold();
        if (options.question.isAnswerCorrect()) {
            // Change the title color to green for correct answers:
            plainBricks[0].textColor = "#00ff00"; // A brick for number in a question title.
            plainBricks[1].textColor = "#00ff00"; // A brick for text in a question title.
        } else {
            // Change the title color to red for incorrect answers:
            plainBricks[0].textColor = "#ff0000"; // A brick for number in a question title.
            plainBricks[1].textColor = "#ff0000"; // A brick for text in a question title.
        }
        return new Promise(function (resolve) {
            resolve();
        });
    });

Links to the related API used in the code:
onRenderQuestionsources, docs
optionssources
options.brickssources
options.questionsources
options.question.isAnswerCorrect()sources
PdfBrick.textColorsources

You can see the complete sample code and test it in action in the Plunker example:
SurveyPDF ― How to highlight incorrect answers in a PDF file

Customized question titles

There is more info about the onRenderQuestion event in our Adorners example's documentation:
https://surveyjs.io/Examples/Pdf-Export?id=survey-pdf-adorners#content-docs

How to customize question choices

The code below shows how to handle the onRenderQuestion event to change the color of choices (to highlight correct choices) for questions of the Radiogroup type.
To modify the text color of choice bricks, a brick's textColor property is used.

This example is based on the previous example's code and extends it with the functionality of finding and highlighting the correct choice in the rendered question.

surveyPDF
    .onRenderQuestion
    .add(function (survey, options) {
        const plainBricks = options.bricks[0].unfold();
        // #region Titles 
        // Change the title color for correct/incorrect answers:
        if (options.question.isAnswerCorrect()) {
            plainBricks[0].textColor = "#00ff00"; 
            plainBricks[1].textColor = "#00ff00"; 
        } else {
            plainBricks[0].textColor = "#ff0000"; 
            plainBricks[1].textColor = "#ff0000";
        }
        // #endregion

        // Find a correct choice and access its text brick:
        const correctChoice = Survey.ItemValue.getItemByValue(options.question.choices, options.question.correctAnswer);
        const correctChoiceIndex = options.question.choices.indexOf(correctChoice);
        const correctChoiceRootBrick = options.bricks[correctChoiceIndex];
        //debugger // <-- Discover the brick structure in DevTools        
        const correctChoiceTextBrick = correctChoiceRootBrick.bricks[1].bricks[0];
        if (correctChoiceIndex === 0) {
            correctChoiceTextBrick = correctChoiceRootBrick.bricks[1].bricks[1].bricks[0];
        }
        // Change the correct choice's text color to green:
        correctChoiceTextBrick.textColor = "#00ff00";

        return new Promise(function (resolve) {
            resolve();
        });
    });

Links to the related API used in the code:
onRenderQuestionsources, docs
optionssources
options.brickssources
options.questionsources
options.question.isAnswerCorrect()sources
Survey.ItemValuesources
Survey.ItemValue.getItemByValue()sources
options.question.choicessources, docs
options.question.choices.indexOf()docs
PdfBrick.textColorsources

You can see the complete sample code and test it in action in the Plunker example:
SurveyPDF - How to highlight correct/incorrect answers together with correct choices in a PDF file

Customized question choices

There is more info about the onRenderQuestion event in our Adorners example's documentation:
https://surveyjs.io/Examples/Pdf-Export?id=survey-pdf-adorners#content-docs