Question T14250
Visible to All Users

Validation depended on custom property

created a year ago (modified a year ago)

Hello

I want to extend the number type, so that the user may specify if the entered number may have decimal places and if yes how many decimals places may be entered.

I know that it's possible to define that by using regex expressions, but I would like to spare my users from that.
So I managed to let the user enter the maximal allowed decimal places.
By entering 0 that would mean that only integer values may be entered.
And if he enters for example 2 that would mean that only numbers with maximal 2 decimal places may be entered.

I managed to create and display the property in the creator:

JavaScript
Survey.Serializer.addProperty("text", { name: "decimals", type: "number", displayName: "Dezimalstellen", isRequired: false, category: "general", minValue: 0, visibleIndex: 9, dependsOn: ["inputType"], visibleIf: function (obj) { return ( obj.inputType === "number" ); } });

But now I did not find any post/documentation, that shows me how I could validate the number entered in the form to satisfy this condition if this property is set.

Can you help me?

Could one solution be to generate and set the corresponding regex expression as validator when this property is set/changed resp. remove the regex validation if the value is deleted?

Perhaps it would be simpler to just validate the entered value if decimal places are set and show a corresponding error message if the entered value does not match the setting?

Answers approved by surveyjs Support

created a year ago (modified a year ago)

Hi Peter,
When you set a Text question's inputType to number, the Text question uses the standard HTML input type=number. However, the input type='number' doesn't have an option to restrict users from entering more than a specified number of decimal places. However, you can specify the step attribute of a number input. I suggest that you use the onSetValue event to set this property value of a number input.

JavaScript
Survey.Serializer.addProperty("text", { name: "decimals", type: "number", displayName: "Dezimalstellen", isRequired: false, category: "general", minValue: 0, visibleIndex: 9, dependsOn: ["inputType"], visibleIf: function (obj) { return ( obj.inputType === "number" ); }, onSetValue: function(surveyElement, value){ // Set the custom 'decimals' value surveyElement.setPropertyValue('decimals', value); const stepValue = Math.pow(10, -value); surveyElement.setPropertyValue('step', stepValue.toFixed(value)); } });

Now, the up and down arrows will increase numbers with the specified number of places.

However, users will still be able to enter an unlimited number of decimal characters. To handle this, you may wish to validate user input on the server side. Handle the survey.onValidateQuestion event, access the value using the options.value, check whether it fits the format and if not, specify options.error.

JavaScript
const surveyJSON = { "logoPosition": "right", "pages": [ { "name": "page1", "elements": [ { "type": "text", "name": "question1", "inputType": "number", "step": "0.01", "decimals": 2 } ] } ] } function validateNumber(numValue, maxDecimalPlaces) { const numberStr = numValue.toString(); const [integerPart, decimalPart] = numberStr.split("."); if (decimalPart && decimalPart.length > maxDecimalPlaces) { return false; } else { return true; } } survey.onValidateQuestion.add((sender, options) => { if(options.question.inputType === 'number' && !!options.question.decimals){ let validationRes = validateNumber(options.value, options.question.decimals); if(!validationRes) options.error = `The number of decimal places should not be greater than ${options.question.decimals}`; } });

Clipboard-File-1.png

I created a demo using a Survey Creator: View Demo. Please note that I access the previewed survey within the creator.onSurveyInstanceCreated event.

For more information on how to validate survey questions using the survey.onValidateQuestion event, refer to the following demo: Custom Form Validation Using an Event.

For the record: if you wish to restrict users and prevent them from entering more than a specified number of decimal places, please consider an Inputmask widget: Masked Input Fields.

I hope this information can help you. Please feel free to contact us if you have any further questions.

    Show previous comments (5)

      Hi Peter,
      When a user manually specifies a custom decimals and step property within a Property Grid and switches to the preview, the onSetValue function of the decimals property is raised. Within the onSetValue function, we calculate the step property based on the supplied decimals value.

      JavaScript
      const stepValue = Math.pow(10, -value); surveyElement.setPropertyValue('step', stepValue.toFixed(value));

      Therefore, a user doesn't get the custom defined step because it is overridden by the code within the onSetValue function.

      If you wish to allow users to define the decimals and step settings independently, you can modify the onSetValue function and do not programmatically modify the step.

      JavaScript
      Survey.Serializer.addProperty("text", { name: "decimals", type: "number", displayName: "Dezimalstellen", isRequired: false, category: "general", minValue: 0, visibleIndex: 9, dependsOn: ["inputType"], visibleIf: function (obj) { return ( obj.inputType === "number" ); } });

      View Demo

      Please let me know if you have any more questions.

      PH PH
      Peter Henzler a year ago

        Ok.
        But if I define a step of 0.05, the user can step in the user interface in 0.05 steps but he can still enter a value like 34.33.
        Is there a way that the entry of a number like 34.33 is not accepted if a step of 0.05 or 0.02 is defined?

        Von: support=surveyjs.io@mg.surveyjs.io <support=surveyjs.io@mg.surveyjs.io>Im Auftrag von Jane [surveyjs Support]
        Gesendet: Donnerstag, 17. August 2023 09:55
        An: Peter Henzler <peter.henzler@scodi.ch>
        Betreff: RE: Validation depended on custom property [T14250]

          Hi Peter,
          The step attribute specifies the interval between legal numbers in an input field with type "number". While setting the step attribute to a certain value like 0.05 will provide a visual cue to the user about the expected increment, it doesn't actually restrict the user from manually entering values that don't adhere to the step.

          If you want to control the values entered, you might need to apply some additional JavaScript validation. I modified the code within the the survey.onValueChanged event to demonstrate how to achieve this:

          JavaScript
          survey.onValidateQuestion.add((sender, options) => { if (options.question.inputType === "number" && !!options.question.step) { const value = parseFloat(options.value); const step = parseFloat(options.question.step); // Scale the values by multiplying with a power of 10 const scale = Math.pow(10, options.question.decimals || 0); const scaledValue = Math.round(value * scale); const scaledStep = Math.round(step * scale); const remainder = scaledValue % scaledStep; if (isNaN(value) || remainder !== 0) { options.error = "Please enter a valid value that adheres to the step."; } } if ( options.question.inputType === "number" && !!options.question.decimals ) { const validationRes = validateNumber( options.value, options.question.decimals ); if (!validationRes) { options.error = `The number of decimal places should not be greater than ${options.question.decimals}`; } } });

          View Demo

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