If an ExpressionValidator can be used instead of the regex validator
(and for the particular example in the question it can), a
solution is to define a "dynamic validator", i.e., one that contains
calculated values.
For the problem in the OP, we can set the GymDura question as:
{
name: "GymDura",
type: "text",
title: "Enter Duration",
inputType: "number",
validators: [
{
type: "expression",
expression: "{GymDura} < {maxValue}",
text: "Value should be less than {maxValue}",
}
]
}
(I use javascript/JSON5 for readability)
The validator is defined by the expression "{GymDura} < {maxValue}" that
contains the calculated value maxValue, which also appears in the text
of the validator.
That calculated value can be simply defined using iif function
as
calculatedValues: [
{
name: "maxValue",
expression: "iif({GymDur} = 'Days', 29.99, iif({GymDur} = 'Months', 11.99, 99.99)"
},
]
Here's a demo snippet:
const json = {
checkErrorsMode: "onValueChanged",
pages: [
{
name: "page1",
elements: [
{
type: "radiogroup",
name: "Gym",
title: "Do you go to GYM",
isRequired: true,
choices: ["Yes", "No"],
},
{
type: "radiogroup",
name: "GymDur",
visibleIf: "{Gym} = 'Yes'",
title: "How long have you been going to GYM",
resetValueIf: "{Gym} = 'No'",
isRequired: true,
choices: ["Days", "Months", "Years"],
},
{
name: "GymDura",
type: "text",
title: "Enter Duration",
inputType: "number",
validators: [
{
type: "expression",
expression: "{GymDura} < {maxValue}",
text: "Value should be less than {maxValue}",
}
],
},
]
},
],
calculatedValues: [
{name: "maxValue", expression: "iif({GymDur} = 'Days', 29.99, iif({GymDur} = 'Months', 11.99, 99.99)"},
],
};
const survey = new Survey.Model(json);
survey.onComplete.add((sender, options) => {
console.log(JSON.stringify(sender.data, null, 3));
});
survey.render(document.getElementById("surveyElement"));
<div id="surveyElement" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; min-height: 100%; height:100%"></div>
<link href="https://unpkg.com/survey-core/survey-core.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-js-ui/survey-js-ui.min.js"></script>
If a regex validator has to be used, the regex property is not dynamic, so
a code based solution can be devised.
One can acces the .validators
property of the question, which is a writable array-like object and can be
manipulated through a few of the array methods it implements. It
can't however be simply assigned to a new array, as the array and
the validators it contains will not be recognized by surveyjs so
the question will have no validators at all.
One can thus add to SurveyComponent constructor in React, or the main
scope of the script in VanillaJS (see runnable snippet below).
function SurveyComponent(){
// ...... original code
const page = survey.getPageByName("page1");
const qGymDur = page.getQuestionByName("GymDur");
const qGymDura = page.getQuestionByName("GymDura");
const allValidators = [...qGymDura.validators]; // store all validators
qGymDura.validators.splice(0, 3); // remove all validators from the question
qGymDur.onPropertyChanged.add((_, options) => {
if (options.name === "value") {
page.clearErrors(); // clear previous errors (if any)
for (let i = 0; i < qGymDur.choices.length; i++) {
if (options.newValue === qGymDur.choices[i].value) {
qGymDura.validators.pop(); // clear previous validator (if any)
qGymDura.validators.push(allValidators[i]);
break;
}
}
}
});
}
The method PageModel#clearErrors
was used to remove errors when a new selection was made.
Runnable snippet:
const json = {
pages: [
{
name: "page1",
elements: [
{
type: "radiogroup",
name: "Gym",
title: "Do you go to GYM",
isRequired: true,
choices: ["Yes", "No"],
},
{
type: "radiogroup",
name: "GymDur",
visibleIf: "{Gym} = 'Yes'",
title: "How long have you been going to GYM",
resetValueIf: "{Gym} = 'No'",
isRequired: true,
choices: ["Days", "Months", "Years"],
},
{
name: "GymDura",
type: "text",
title: "Enter Duration",
inputType: "number",
validators: [
{
type: "regex",
regex: "^(?:[0-9]|[1-2][0-9])$",
text: "Value should be less than 29.99",
},
{
type: "regex",
regex: "^(?:[0-9]|1[01])$",
text: "Value should be less than 11.99",
},
{
type: "regex",
regex: "^(?:d{1,2})(?:.d{1,2})?$",
text: "Value should be less than 99.99",
},
],
},
],
},
],
};
const survey = new Survey.Model(json);
survey.onComplete.add((sender, options) => {
console.log(JSON.stringify(sender.data, null, 3));
});
survey.render(document.getElementById("surveyElement"));
const page = survey.getPageByName("page1");
const qGymDur = page.getQuestionByName("GymDur");
const qGymDura = page.getQuestionByName("GymDura");
const allValidators = [...qGymDura.validators]; // store all validators
qGymDura.validators.splice(0, 3); // remove all validators from the question
qGymDur.onPropertyChanged.add((_, options) => {
if (options.name === "value") {
page.clearErrors(); // clear previous errors (if any)
for (let i = 0; i < qGymDur.choices.length; i++) {
if (options.newValue === qGymDur.choices[i].value) {
qGymDura.validators.pop(); // clear previous validator (if any)
qGymDura.validators.push(allValidators[i]);
break;
}
}
}
});
<div id="surveyElement" style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; min-height: 100%; height:100%"></div>
<link href="https://unpkg.com/survey-core/survey-core.min.css" type="text/css" rel="stylesheet">
<script type="text/javascript" src="https://unpkg.com/survey-core/survey.core.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/survey-js-ui/survey-js-ui.min.js"></script>