survey-library icon indicating copy to clipboard operation
survey-library copied to clipboard

Server Side Data Validation with SurveyJs Definition

Open dasboe opened this issue 1 year ago • 11 comments

Are you requesting a feature, reporting a bug or asking a question?

question

What is the expected behavior?

Given SurveyJs data and a SurveyJs definition, provide a solution/example which shows how to validate data with a given SurveyJs definition on the server (Node.js).

This must be one of the most common use cases to have data consistency but I can not find a single running example. These Issues are asking similar questions, but it is not sufficiently answered:

https://github.com/surveyjs/survey-library/issues/2001 https://github.com/surveyjs/survey-library/issues/1340

Provide the test code and the tested page URL (if applicable)

Test code

This code is using a hypothetical validateSurveyData function

const surveyJsDefinition = {
 "pages": [
  {
   "name": "page1",
   "elements": [
    {
     "type": "text",
     "name": "question1",
     "maxLength": 10
    }
   ]
  }
 ]
}

// returns true
validateSurveyData(surveyJsDefinition, { "question1": "text" })

// returns false because question1 string is longer than maxLength 10 
validateSurveyData(surveyJsDefinition, { "question1": "long text with more than 10 characters" })

// returns false because question2 is not part of the survey definition
validateSurveyData(surveyJsDefinition, { "question2": "text" })

dasboe avatar Apr 18 '23 09:04 dasboe

Hello @dasboe, Thank you for contacting us.

The SurveyJS Form Library server-side survey data validation allows you to validate values users entered in a form/survey fields. To validate user input on the server side, handle the onServerValidateQuestions event. The event handler is executed on navigation to the next page and on survey completion.

The onServerValidateQuestions event handler accepts the survey as the first argument and an object with the following fields as the second argument:

  • data - An object that contains question values.
  • errors - An object for your error messages. Set error messages as follows: errors["questionName"] = "My error message";
  • complete() - A method that you should call when the request to the server has completed.

Please check the following online demo on our website: Server-Side Form Validation Using an Event.

In this server-side validation example, you should enter a country name into the form field. A callback assigned to the onServerValidateQuestions event handler will fetch a list of countries and check whether the entered country is in it. If the country is not found, the form field will display a validation error.

Let me know if this feature works for you.

JaneSjs avatar Apr 21 '23 14:04 JaneSjs

Thank you very much for your detailed response, but I'm afraid this is not what I was asking for. I was already aware of the onServerValidateQuestions event, but that is not my use case (see same answer/response here https://github.com/surveyjs/survey-library/issues/2001#issuecomment-589983897).

Maybe it helps if I lay out my use case:

  • We want to let users create surveys with the survey creator with all functionality (logic, validation, ...).

  • The survey definition of these surveys are saved on our servers and will be used for public surveys. Eventually when the data of a filled in survey is send to our servers, we would like to validate on the server side the integrity of the data with the survey definition.

This is why I gave the example above (hypothetical validateSurveyData function) which checks the integrity (true or false) of the data of a filled in survey with the survey definition.

A possible solution might be given here https://github.com/surveyjs/survey-library/issues/1340#issuecomment-422296676 but I don't know how I would do this without an example.

dasboe avatar Apr 24 '23 16:04 dasboe

It seems there are currently no backend solutions for SurveyJs, meaning running SurveyJs on backend for any purposes (including the one I was asking for) is not an option.

@JaneSjs Is this correct?

https://surveyjs.io/documentation/backend-integration

dasboe avatar May 02 '23 10:05 dasboe

@JaneSjs Is there any update on this? How do we validate the asynchronous functions on the server side? @dasboe, were you able to solve this?

rajeshn95 avatar Aug 25 '23 10:08 rajeshn95

I'm not finished with my solution, but have also been looking for server side validation using the definition. Since my server is using NodeJS, I simply imported Survey from survey-core. There is a validate method, and errors + error messages can be extracted from questions inside pages.

Nichopotatamus avatar Jan 13 '24 19:01 Nichopotatamus

One issue that seems to remain for me with validation via Node is that if you load choices by url, those choices are not loaded (cannot be?) and you will get a validation error. I haven't been able to fix this yet.

I'm also not sure if expressions are being run as some expressions that determine if a question is required, don't seem to be enforcing requirement.

cworsley4 avatar Mar 20 '24 14:03 cworsley4

One issue that seems to remain for me with validation via Node is that if you load choices by url, those choices are not loaded (cannot be?) and you will get a validation error. I haven't been able to fix this yet.

I'm also not sure if expressions are being run as some expressions that determine if a question is required, don't seem to be enforcing requirement.

Could you give me an example of a survey definition that has this issue? It would be interesting to try out here to see if it works or not. And if it does, share my setup.

Nichopotatamus avatar Mar 31 '24 02:03 Nichopotatamus

Hello Everyone, Please accept my apologies for the delayed reply.

SurveyJS Forms run on a client-side. Therefore, SurveyJS Form Library provides the functionality which allow you to validate a user input on the client-side. To ensure that users enter values in a specified format, you can apply an input mask and configure a different kind of user input validation.

Therefore, as soon as you enabled client-side validation, you may expect that users submit forms only when all form fields are valid.

  • To ensure that a survey JSON is correctly formatted and structured, you can use the survey.jsonErrors array.
const survey = SurveyModel(yourJSON);
if(!!survey.jsonErrors) {
  // A survey JSON contains errors
  //...
}
  • To check whether a survey contains validation errors, you can call the survey.validate function.
const survey = new SurveyModel(json);
survey.data = userResponse;
const isValidResponse = survey.validate();
//...

Should you have any additional questions,

JaneSjs avatar Apr 02 '24 10:04 JaneSjs

@JaneSjs Thank you very much for the answer. Still I think this goes against the golden rule of Web development: "Never Trust Data from the Client".

We are working with very sensible data, and it's essential to check if the data is valid on the server side because of multiple reasons:

  • client data could be of an old format
  • client data could be altered/hacked
  • client side validation failed

Therefor I think the SurveyJs Team should maybe think about providing a server side validation solution and I would really appreciate if you could maybe discuss this with your team.

dasboe avatar Apr 02 '24 10:04 dasboe

One issue that seems to remain for me with validation via Node is that if you load choices by url, those choices are not loaded (cannot be?) and you will get a validation error. I haven't been able to fix this yet.

I'm also not sure if expressions are being run as some expressions that determine if a question is required, don't seem to be enforcing requirement.

Could you give me an example of a survey definition that has this issue? It would be interesting to try out here to see if it works or not. And if it does, share my setup.

I can try and post an example later. As I'm not near my machine currently. But as surveyjs uses XHR to make requests, this wouldn't work in Node as Node doesn't provide this API. So it wouldn't be possible pull results from an external source

cworsley4 avatar Apr 02 '24 12:04 cworsley4

One thing that you could do to "solve" the restful questions issue is polyfill XMLHttpRequest object in node.

I'm sure the is plenty still that won't work quite right but this at least will get you over this hump.

import { XMLHttpRequest } from 'xmlhttprequest';

global.XMLHttpRequest = XMLHttpRequest;

There could be a better package out there than https://www.npmjs.com/package/xmlhttprequest (published 8 years ago) but again, this should help you get started if this is a road you're going done.

/cc @dasboe

cworsley4 avatar Apr 02 '24 18:04 cworsley4