Question T14687
Visible to All Users

Customising existing questions

created a year ago

Hi,

We wrote the following code to extend the functionality of the existing question types:

JavaScript
import { CustomWidgetCollection, Serializer } from "survey-core" export const loadConformanceType = () => {} CustomWidgetCollection.Instance.add({ name: "conformance", isFit: function (element: any) { * return element.getType() == "text" * }, init() { * Serializer.addProperty("text", { * name: "conformant:boolean", default: false, category: "general", }) }, isDefaultRender: true, afterRender: function (question: any, el: any) { var mainDiv = document.createElement("div") mainDiv.textContent = "conformance boolean UI" mainDiv.style.backgroundColor = "green" mainDiv.style.color = "white" mainDiv.style.backgroundColor = "green" mainDiv.style.marginTop = "10px" mainDiv.style.padding = "3px" mainDiv.style.textAlign = "center" el.append(mainDiv) mainDiv.style.display = !question.conformant ? "none" : "" question.registerFunctionOnPropertyValueChanged("conformant", function () { mainDiv.style.display = !question.conformant ? "none" : "" }) }, })

The above code adds a property to the text question called "conformant", when that property is toggled some extra UI is appended to that question. However, what we want is code that adds this property/UI to all types of questions, not just "text". One thing we tried is changing the question type in the code lines highlighted with "*" in the code. So we would write the exact same code for each of the question types but change the type from "text" to "dropdown" for example. We had two problems with that approach:
1- The approach does not work with the boolean question type. This is an example of the text type (works OK):

Clipboard-File-1.png

but we change the type to boolean we get this (does not work as expected):

Clipboard-File-2.png

As you can see the change affects all the boolean elements in the page even the ones in the property area, which is not what we want. We only want the question in the survey page to be affected.

2- If we go with this approach we have duplicate the above code 17 or 18 times to cover all the question types. Is there a way to make the above code work for all the questions at once? we tried replacing the question type in the highlighted lines above with "question" which is the parent class of all the question types. Although the Serializer added the property checkbox correctly, clicking on it did not trigger any changes. So afterRender and registerFunctionOnPropertyValueChanged were not being called at all.

JavaScript
... isFit: function (element: any) {   return element.getType() == "question" }, ... init() {   Serializer.addProperty("question", {     name: "conformant:boolean",     default: false,     category: "general",   }) }, ...

If you have any suggestions regarding problems 1 and 2 above please let us know. If you think we going completely in the wrong direction and there is a better way to achieve this please point us to it.

Thanks.
Aleksandra

Answers approved by surveyjs Support

created a year ago (modified a year ago)

Hello Aleksandra,
To register a custom widget and a custom 'confirmant' property for all question types, please update your code as follows.

  • Register a custom property for the base question class.
JavaScript
Serializer.addProperty("question", { name: "conformant:boolean", default: false, category: "general" }); ...
  • Override the isFit function to check whether element is an instance of Question, and whether this element has the conformant option enabled.
JavaScript
isFit: function (element) { const isSurveyQuestion = element instanceof Question; const isConformantEnabled = !!element.conformant; return isSurveyQuestion && isConformantEnabled; }
  • Also, no need to subscribe to the conformant property value changed. The afterRender function will be called each time a question is rendered. So, you can update the code as follows.
JavaScript
afterRender: function (question, el) { var mainDiv = document.createElement("div"); mainDiv.textContent = "conformance boolean UI"; mainDiv.style.backgroundColor = "green"; mainDiv.style.color = "white"; mainDiv.style.backgroundColor = "green"; mainDiv.style.marginTop = "10px"; mainDiv.style.padding = "3px"; mainDiv.style.textAlign = "center"; el.append(mainDiv); mainDiv.style.display = !question.conformant ? "none" : ""; }

View Demo

Let me know if you have any further questions.

P.S. We hope you enjoyed the level of service you received. If so, we would love if you could leave your feedback on SurveyJS page at g2.com. As we’re building our business, every review helps build credibility for future customers and your feedback would be greatly appreciated.

    Show previous comments (6)

      Hello Aleksandra,
      Thank you for the update. From what I gather, you use a custom widget option to render additional elements for built-in survey questions. Please let me note that a custom widget option though may work but is considered a legacy option. If you use React or Angular, and wish to extend default survey components, consider either of the following options:

      With this option, you can programmatically build a new component which is composed of multiple built-in survey components. In reference to your screenshot, this option will be suitable for your usage scenario. You may wish to build a composite component using two single-line text fields, and a radiogroup. Values of inner components will be saved within survey results.

      • Extend a built-in React/Angular survey component. With this option, you would build a custom component on top of a built-in survey question class.

      If you still wish to proceed with custom widgets, please refer to the following guide for more information on how to update the underlying question value when the value of a custom widget input is updated: Create Custom Widgets in jQuery and Knockout.

      Should you have any more questions, I'm here to help.

        Hello Jane,
        It looks like we are back to square one. We have already tried composite component approach… correct me if i am wrong but it looks like the composite component lacks the ability to configure the question in the designer mode.
        We've run into difficulties when it comes to customizing it to match the desired format and functionality we have in mind. Specifically, we are interested in implementing a question type that combines a rating scale, a boolean response, an open-ended comment and the file upload without bundling them up in the panel.

        To provide some context, we would like to create survey questions that look something like this:

        How would you rate your recent stay with us? (Rating Scale)

        Very Satisfied
        Satisfied
        Neutral
        Dissatisfied
        Very Dissatisfied

        Would you recommend us to your friends? (Boolean Response)
        Yes/No

        Provide your comment here (Open-ended Comment)

        We have explored the option of configuring a composite question type, following the approach suggested here: https://surveyjs.io/form-library/documentation/customize-question-types/create-composite-question-types. While we succeeded in building a custom composite, we encountered an issue where the questions could not be configured in the Designer mode.

        Is it possible to create a custom question type by combining existing question types while retaining configurability within the designer mode?

          Hello Aleksandra,
          Thank you for the update. Custom components hide settings of their inner questions. Still, you can enable users to modify settings of questions which are located within a custom component. For this, you need to add settings at the level of your custom component. These component settings would update settings of its inner questions. Please take a look at the following tutorial and the demo enclosed there: Create Composite Question Types. In the Add Custom Properties to Composite Question Types section, you'll find a code snippet which shows how to update settings of an inner question.

          Please let me know if you have additional questions.