0

I want to create a SurveyJS matrix with rows that contain a text & HTML element. Thus, the HTML content should change in each row. The Survey is a reasoning test that contains a text statement and a symbol pattern that I create by combining HTML code with some CSS. In the remaining columns it contains the response if the statement correctly describes the symbol pattern.

Below is an example of creating the matrix with the correct column types and row information. If I pass a static HTML to the HTML column it gets displayed correctly. But I am stuck at accessing the pattern property of each row to dynamically change the HTML.

const matrix_dynamic_html = {
    "elements": [
      {
        type: "matrixdropdown",
        name: "Test",
        title: "my_title",
        description: "my_pattern",
        columns: [
          {
            name: "pattern",
            title: "Pattern",
            cellType: "html",
            // here we have to access the HTML for each row 
            html: "{row.pattern}"
          },
          {
            name: "response",
            title: "response",
            cellType: "radiogroup",
            "choices": [
              {
                "value": 0,
                "text": "Incorrect"
              },
              {
                "value": 1,
                "text": "Correct"
              }
            ],
            "showInMultipleColumns": true,
            "colCount": 1
          }
        ],
        rows: [
          {
            value: "question_1",
            text: "This is question 1.",
            pattern: generate_html("ques_1"),
          },
          {
            value: "question_2",
            text: "This is question 2.",
            pattern: generate_html("ques_2"),
          },
          {
            value: "question_3",
            text: "This is question 3.",
            pattern: generate_html("ques_3"),
          },
          {
            value: "question_4",
            text: "This is question 4.",
            pattern: generate_html("ques_4"),
          }
        ],
        rowTitleWidth: "50%",
      }
    ],
    "showQuestionNumbers": false
  };

I use the generate_html function to generate the HTML and have checked that this works properly.

I appreciate any input on how to access the pattern property or adapt the setup of the matrix to be able to dynamically change the HTML. Any help is welcome.

1 Answer 1

0

Your generate_html() function will not get called during the rendering of the question the way you have applied it. Also, I don't believe you can set an expression to the html property of the HTML question.

Instead you need to add a handler to the onAfterRenderMatrixCell event. It will pass an options parameter that contains a reference to the html object of the cell that's being rendered. You can then manipulate the contents of that cell as you wish by setting the innerHTML property.

To find out which row you are on you can use the options.row.name value, which holds the id of the row.

First you should normalize your JSON to remove the generate_html() references and the {row.pattern} expression:

const matrix_dynamic_html =  {
      pages: [
        {
          name: "page1",
          elements: [
            {
              type: "matrixdropdown",
              name: "MyMatrixQuestion",
              title: "my_title",
              description: "my_pattern",
              columns: [
                {
                  name: "pattern",
                  title: "Pattern",
                  cellType: "html",
                  html: "<span style='color: red'>original html</span>",
                },
                {
                  name: "response",
                  title: "response",
                  cellType: "radiogroup",
                  colCount: 1,
                  showInMultipleColumns: true,
                  choices: [
                    {
                      value: 0,
                      text: "Incorrect",
                    },
                    {
                      value: 1,
                      text: "Correct",
                    },
                  ],
                },
              ],
              rows: [
                {
                  value: "question_1",
                  text: "This is question 1.",
                },
                {
                  value: "question_2",
                  text: "This is question 2.",
                },
                {
                  value: "question_3",
                  text: "This is question 3.",
                },
                {
                  value: "question_4",
                  text: "This is question 4.",
                },
              ],
              rowTitleWidth: "50%",
            },
          ],
        },
      ],
      showQuestionNumbers: "off",
    }

Finally create the event handler like so:

import React from "react";
import { Model } from "survey-core";
import { Survey } from "survey-react-ui";
import "survey-core/defaultV2.min.css";
import "./index.css";
import { json } from "./json";

function SurveyComponent() {
  const survey = new Model(json);
  survey.onComplete.add((sender, options) => {
    console.log(JSON.stringify(sender.data, null, 3));
  });

// Event handler for cell rendering:
  survey.onAfterRenderMatrixCell.add((sender, options) => {
    if (options.cellQuestion.jsonObj.name == "pattern") {
      options.htmlElement.innerHTML =
        "<span style='color: Green'>new html for " +
        options.row.name +
        "</span>";
    }
  });

  return <Survey model={survey} />;
}

export default SurveyComponent;

You can see this example working in this sandbox: https://codesandbox.io/p/sandbox/matrix-cell-render-event-demo-pc7sfc?file=%2Fsrc%2FSurveyComponent.jsx

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.