Question T18152
Visible to All Users

Universal plugin system

created 8 months ago

Hi SurveyJS Team,

we managed to implement a custom feature using the official SurveyJS documentation and we want to hide it behind a feature flag.

Just for clarity, we have decided to register a new boolean value in the property grid for questions of type radio group, adding the possibility to hide the input circles and mark the selected item with a colored border. This feature required interfering with multiple parts of the library.

First, we had to register the new property in the grid, this is done globally on the Survey module:

TypeScript
import * as Survey from 'survey-core'; Survey.Serializer.addProperties('question', [ { name: 'hideChoiceInput', type: 'boolean', category: 'choices', }, ]);

Second, we had to register callbacks for each survey model instance, after it was created with the new keyword, and make sure that it is called whenever we are working with Survey Creator or Survey Viewer:

TypeScript
import { Model } from 'survey-react'; const survey = new Model(); survey.onAfterRenderQuestion.add(restyleChoiceQuestions); survey.onAfterRenderMatrixCell.add(restyleChoiceQuestions);

Was our approach correct? Is there a way to register these mechanisms in a single step, perhaps by registering the lifecycle hook callbacks globally? Is there a way to create an "universal plugin" for SurveyJS, which can be registered in one place for Creator and Viewer, globally or locally for all the required mechanisms?

Thank you all in advance!

Answers approved by surveyjs Support

created 8 months ago

Hello Helen,
Thank you for reaching out to us. From what I gather, you wish to achieve the following:

  • Add a custom property which should be available in a property grid.
  • Implement SurveyModel functions and override question rendering.

It would be possible to implement a plugin which would attach required functions to a survey which is being run. Consider the following code.

customRenderingPlugin.js

JavaScript
function attachCustomRenering(survey) { function restyleChoiceQuestions(survey, options) { console.log("Restyling choice questions or matrix cells..."); } survey.onAfterRenderQuestion.add(function (sender, options) { restyleChoiceQuestions(sender, options); }); survey.onAfterRenderMatrixCell.add(function (sender, options) { restyleChoiceQuestions(sender, options); }); } export { attachCustomRenering };

Use a custom plugin when a survey is run.

SurveyComponent.jsx

JavaScript
import { attachCustomRenering } from "./customRenderingPlugin"; import { Model } from "survey-core"; const survey = new Model(json); attachCustomRenering(survey);

SurveyCreatorComponent.jsx

JavaScript
import { attachCustomRenering } from "./customRenderingPlugin"; creator.onSurveyInstanceCreated.add((sender, options) => { if (options.area === "preview-tab") { attachCustomRenering(options.survey); } });

However, it's important to note that the Serializer.addProperty should be called regardless of the current creator mode (design/preview). To make a custom property available in design mode, you would require to call the Serializer.addProperty function at the application startup.

JavaScript
import { Serializer } from "survey-core"; Serializer.addProperty("question", { name: "hideChoiceInput", type: "boolean", category: "choices", });

If you wish to hide the custom property from the Property Grid under a condition, you can implement the creator.onShowingProperty function.

Please let me know if these recommendations help.

    Comments (2)

      Thank you for the comprehensive answer!

      On that topic, is there a way to decide inside the onAfterRenderQuestion and onAfterRenderMatrixCell callbacks, if the survey is displayed in creator or in viewer?

      Thanks!

        Hello Helen,
        You can check whether a survey appears in preview or design mode using the survey.isDesignMode setting. Please let me know if you have further questions.