Documentation Docs
Documentation Docs

Customize Survey Questions in PDF

SurveyJS PDF Generator is designed to render survey questions into PDF optimally. At the same time, our tool includes APIs that allow you to adjust and customize question rendering to PDF as per your requirements. This help topic gives an overview of these APIs.

HTML Rendering

Questions of the HTML type enable you to add any custom elements to your survey. However, complex HTML markup is difficult to render into PDF primitives without losing interactivity. If the markup mostly consists of textual content, it is rendered into PDF as selectable text. Complex HTML markup is rendered as images. If you want to override this behavior, set the htmlRenderAs property to one of the following values:

  • "standard"
    Renders HTML questions as selectable text.

  • "image"
    Renders HTML questions as images.

  • "auto" (default)
    Selects between the "standard" and "image" modes automatically based on the HTML content.

const pdfDocOptions = {
  htmlRenderAs: "image" // or "standard" | "auto"
};

const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);

// In modular applications:
import { SurveyPDF } from "survey-pdf";
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);

You can override this property for individual HTML questions. Set the question's renderAs property to "standard" or "image" in the survey JSON schema:

const surveyJson = {
  "elements": [{
    "type": "html",
    // ...
    "renderAs": "image" // or "standard"
  }]
};

Matrix Rendering

Single-Select Matrix, Multi-Select Matrix, and Dynamic Matrix questions can be rendered into PDF as tables or lists. Tables are used if matrix content fits into the available page width. Otherwise, matrix content is rendered as a list.

Matrix rendered as a table

SurveyJS PDF Generator: Render a matrix as a table in a PDF form

Matrix rendered as a list

SurveyJS PDF Generator: Render a matrix as a list in a PDF form

If you want to render all matrices as lists, regardless of whether they fit into the page as tables or not, set the matrixRenderAs property to "list":

const pdfDocOptions = {
  matrixRenderAs: "list"
};

const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);

// In modular applications:
import { SurveyPDF } from "survey-pdf";
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);

You can override this property for individual matrix questions. Set the question's renderAs property to "list" in the survey JSON schema:

const surveyJson = {
  "elements": [{
    "type": "matrix",
    // ...
    "renderAs": "list"
  }]
};

Image Rendering

Image questions have an imageFit property that specifies how images should fit into their containers. If exported images should apply this property, enable the applyImageFit option. Please note that with this option, the quality of images may be lower because they pass through several conversions.

const options = {
  applyImageFit: true
};

const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);

// In modular applications:
import { SurveyPDF } from "survey-pdf";
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);

If applyImageFit is disabled, exported images fill the entire container and do not preserve their aspect ratio, but their quality remains the same because they are exported as is.

Read-Only Question Rendering

Read-only questions can be rendered as plain text surrounded by custom primitives or as interactive AcroForms switched to their native read-only state. To specify the desired render mode, set the readonlyRenderAs property to "text" or "acroform":

const pdfDocOptions = {
  readonlyRenderAs: "text" // or "acroform" | "auto"
};

const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);

// In modular applications:
import { SurveyPDF } from "survey-pdf";
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);

The default value of the readonlyRenderAs property is "auto". In this mode, SurveyJS PDF Generator renders most elements as plain text but uses AcroForms for File Upload questions and links.

You can override the readonlyRenderAs property value for individual questions:

import { Model } from "survey-core";
import { SurveyPDF } from "survey-pdf";

const surveyJson = { ... };
const pdfDocOptions = { ... };

const survey = new Model(surveyJson);
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);

surveyPdf.data = survey.data;
surveyPdf.getAllQuestions().forEach(question => {
  if (question.getType() === "file") {
    question.readOnly = true;
    question.readonlyRenderAs = "text";
  }
});
surveyPdf.save(filename);

Custom Rendering

Any PDF document consists of bricks—simple elements with specified content, size, and location. A brick API is described in the PdfBrick API reference. When you work with bricks, you need to understand the structure of the bricks that compose the currently rendered questions and access the bricks that contain the element you want to customize, such as the question title, description, or an individual choice. The easiest way to understand the brick structure is to insert a debugger into an onRenderQuestion event handler and investigate the options.bricks array using a browser's developer tools:

const surveyPdf = new SurveyPDF.SurveyPDF(surveyJson, pdfDocOptions);
surveyPdf.onRenderQuestion.add((_, options) => {
  debugger;
});

// In modular applications:
import { SurveyPDF } from "survey-pdf";
const surveyPdf = new SurveyPDF(surveyJson, pdfDocOptions);
surveyPdf.onRenderQuestion.add((_, options) => {
  debugger;
});

The following code gives an example of brick customization. In this code, question titles are colored differently depending on whether the question answer is correct:

import { ItemValue } from "survey-core";

surveyPdf.onRenderQuestion.add((_, options) => {
  const plainBricks = options.bricks[0].unfold();
  // Color the title green for correct answers or red for incorrect answers
  const color = options.question.isAnswerCorrect() ? "#00ff00" : "#ff0000";
  plainBricks[0].textColor = color; // A brick that renders a question number
  plainBricks[1].textColor = color; // A brick that renders a question title

  // Find a correct answer and access its text brick
  const correctAnswer = ItemValue.getItemByValue(options.question.choices, options.question.correctAnswer);
  const correctAnswerIndex = options.question.choices.indexOf(correctAnswer);
  const correctAnswerRootBrick = options.bricks[correctAnswerIndex];
  const correctAnswerTextBrick = (correctAnswerIndex === 0)
    ? correctAnswerRootBrick.unfold()[4]
    : correctAnswerRootBrick.unfold()[1];
  // Color the correct answer green
  correctAnswerTextBrick.textColor = "#00ff00";
});

View Example on Plunker

For more examples of question customizations, refer to the following demo: Use Adorners.

Send feedback to the SurveyJS team

Need help? Visit our support page

Copyright © 2024 Devsoft Baltic OÜ. All rights reserved.

Your cookie settings

We use cookies on our site to make your browsing experience more convenient and personal. In some cases, they are essential to making the site work properly. By clicking "Accept All", you consent to the use of all cookies in accordance with our Terms of Use & Privacy Statement. However, you may visit "Cookie settings" to provide a controlled consent.

Your renewal subscription expires soon.

Since the license is perpetual, you will still have permanent access to the product versions released within the first 12 month of the original purchase date.

If you wish to continue receiving technical support from our Help Desk specialists and maintain access to the latest product updates, make sure to renew your subscription by clicking the "Renew" button below.

Your renewal subscription has expired.

Since the license is perpetual, you will still have permanent access to the product versions released within the first 12 month of the original purchase date.

If you wish to continue receiving technical support from our Help Desk specialists and maintain access to the latest product updates, make sure to renew your subscription by clicking the "Renew" button below.