Question T14052
Visible to All Users

"itemvalue" custom property showing/ hiding depending on a property on the question level ( SuveyJs Creator )

created 2 years ago

Dear SurveyJs Team,

i am stuck in a process in SuveyJs Creator and would like your support.

My business case is i want to introduce a scoring possibility per question, therefore I offer the user a checkbox per question to ask him if this question X has scoring. Questions affected should be all questions with itemvalue choices, like dropdown, radiogroup and checkbox.

The following screenshot, shows the hasScoring property under general settings for the question.
Clipboard-File-1.png

While this screenshot, shows the score property on the choices itemvalue level.
Clipboard-File-2.png

Moreover, this is how the json would look like:

JavaScript
{ "type": "dropdown", "Text": "Do you like Milk?", "hasScoring": true, "choices": [ { "value": "Item 1", "text": "Yes", "score": 10 }, { "value": "Item 2", "text": "No", "score": 10 }, { "value": "Item 3", "text": "Some", "score": 5 } ] }

What i want is, to show and hide score property in the choices matrix table, depending on the hasScoring property of the question. Since hasScoring is on a higher level, dependsOn and visibleIf would not work.

Moreoever, this is how i create the properties.

JavaScript
surveyjsConfig.addProperty('question', { name: 'hasScoring', type: 'boolean', displayName: 'Has scoring?', category: 'general', visibleIndex: 0, }, ); surveyjsConfig.addProperty('itemvalue', { name: 'score', type: 'number', displayName: 'Score%', visibleIndex: 2, }, );

I managed to show and hide the score property on the initial state using onShowingProperty.

JavaScript
this.editor.onShowingProperty.add((_, options) => { if(options.obj.getType() === 'itemvalue') { if(options.property.name === 'score') { options.canShow = options.parentObj.getPropertyValue('hasScoring'); } } });

But i am stuck and not able to make it hide and show, on value change of hasScoring. I tried onModified, but the canShow option does not exist.

Looking forward to your reply.

With regards
Abdullah

Answers approved by surveyjs Support

created 2 years ago

Hello Abdullah,
If you wish to introduce a custom property for questions which have choices (i.e. Checkbox, Radiogroup), you can register choices for a selectbase survey object.

JavaScript
Survey.Serializer.addProperty('selectbase', { name: 'hasScoring', type: 'boolean', displayName: 'Has scoring?', category: 'general', visibleIndex: 0, } );

To show/hide a choice's score property based on a parent question's hasScoring option, register a visibleIf property function and check the parent question's property.

JavaScript
Survey.Serializer.addProperty('itemvalue', { name: 'score', type: 'number', displayName: 'Score%', visibleIf: function (obj) { return obj.locOwner.hasScoring; }, visibleIndex: 2, }, );

View Demo

Please let me know if you have additional questions.

    Show previous comments (1)

      Hello,
      You're very welcome.

      1. If you wish to ensure that the sum of score values for a particular question doesn't exceed 100%, you can handle the creator.onPropertyValidationCustomError event, check the current choice's score value, and display an error if the value exceeds a limit.

      2. From what I gather, you wish to display a label after the entered value.
        If you use a regular text property, you can subscribe to the survey.onMatrixCellValueChanging event of the property grid survey and programmatically modify a user input value. Consider this example:

      JavaScript
      Survey.Serializer.addProperty('itemvalue', { name: 'score', type: 'text', displayName: 'Score%', visibleIf: function (obj) { return obj.locOwner.hasScoring; }, visibleIndex: 2, }, ); creator.onPropertyGridSurveyCreated.add((sender, options) => { options.survey.onMatrixCellValueChanging.add((sender, options) => { if(options.name === 'score'){ options.value = options.value + "%"; } }); });

      Clipboard-File-1.png

      However, with this option, users can enter not only numeric values. Therefore, it would be necessary to programmatically validate an input value within the onMatrixCellValueChanging event and correct it, if necessary.

      An alternative option, is to keep the numeric input for the score property, and use the % symbol in a property description as you currently do (displayName: 'Score, %').
      Additionally, validate a property value within the onPropertyValidationCustomError event to prevent users from specifying more than 100% score for a single question.
      Clipboard-File-2.png
      View Demo

      Also, to allow the property grid editor to fully display an error message, I would suggest that you make the score property be available only in a detail form. For this, set the showMode property to "form".

      JavaScript
      Survey.Serializer.addProperty('itemvalue', { name: 'score', type: 'number', showMode: "form", displayName: 'Score, %', visibleIf: function (obj) { return obj.locOwner.hasScoring; }, visibleIndex: 2, }, ); creator.onPropertyValidationCustomError.add((sender, options) => { if(options.propertyName === 'score'){ let currentTotalScore = 0; options.obj.choices.forEach(c => { if(typeof c.score === 'number'){ currentTotalScore += c.score }}); if(currentTotalScore + options.value > 100){ options.error = "Total score should be < 100" } } });

      View Demo
      Clipboard-File-3.png

      If you wish to keep the score property in a table editor, you can validate the entered value using the onMatrixCellValueChanging and correct it, if it exceeds 100.

      I hope this helps. Drop me a line if you have additional questions.

        Thank you for your speedy response!

        Concerning question number 2, i was wondering if it was doable without going to text and keeping the property as a number. Because i found solutions online, but only with text.

          Hello,
          Unfortunately, the number input only allows entering numeric values. Please consider alternatives described above.

          Let me know if you have further questions.