Skip to content

Commit

Permalink
Improve setValueIf/setValueExpression fix #7196 (#7197)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtelnov authored Oct 20, 2023
1 parent 328f62e commit 95ecc0f
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 34 deletions.
51 changes: 34 additions & 17 deletions src/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class TriggerExpressionInfo {
runner: ExpressionRunner;
isRunning: boolean;
constructor(public name: string, public canRun: () => boolean, public doComplete: () => void) {}
runSecondCheck: (keys: any) => boolean = (keys: any): boolean => false;
}

/**
Expand Down Expand Up @@ -143,7 +144,8 @@ export class Question extends SurveyElement<Question>
this.clearValue();
this.updateValueWithDefaults();
});
this.addTriggerInfo("setValueIf", (): boolean => true, (): void => this.runSetValueExpression());
const setValueIfInfo = this.addTriggerInfo("setValueIf", (): boolean => true, (): void => this.runSetValueExpression());
setValueIfInfo.runSecondCheck = (keys: any): boolean => this.checkExpressionIf(keys);
this.registerPropertyChangedHandlers(["width"], () => {
this.updateQuestionCss();
if (!!this.parent) {
Expand Down Expand Up @@ -522,30 +524,47 @@ export class Question extends SurveyElement<Question>
};
}
private setValueExpressionRunner: ExpressionRunner;
private ensureSetValueExpressionRunner(): void {
if(!this.setValueExpressionRunner) {
this.setValueExpressionRunner = new ExpressionRunner(this.setValueExpression);
this.setValueExpressionRunner.onRunComplete = (res: any): void => {
if(!this.isTwoValueEquals(this.value, res)) {
this.value = res;
}
};
} else {
this.setValueExpressionRunner.expression = this.setValueExpression;
}
}
private runSetValueExpression(): void {
if(!this.setValueExpression) {
this.clearValue();
} else {
if(!this.setValueExpressionRunner) {
this.setValueExpressionRunner = new ExpressionRunner(this.setValueExpression);
this.setValueExpressionRunner.onRunComplete = (res: any): void => {
if(!this.isTwoValueEquals(this.value, res)) {
this.value = res;
}
};
} else {
this.setValueExpressionRunner.expression = this.setValueExpression;
}
this.ensureSetValueExpressionRunner();
this.setValueExpressionRunner.run(this.getDataFilteredValues(), this.getDataFilteredProperties());
}
}
private checkExpressionIf(keys: any): boolean {
this.ensureSetValueExpressionRunner();
if(!this.setValueExpressionRunner) return false;
return new ProcessValue().isAnyKeyChanged(keys, this.setValueExpressionRunner.getVariables());
}
private triggersInfo: Array<TriggerExpressionInfo> = [];
private addTriggerInfo(name: string, canRun: ()=> boolean, doComplete: () => void): void {
this.triggersInfo.push(new TriggerExpressionInfo(name, canRun, doComplete));
private addTriggerInfo(name: string, canRun: ()=> boolean, doComplete: () => void): TriggerExpressionInfo {
const info = new TriggerExpressionInfo(name, canRun, doComplete);
this.triggersInfo.push(info);
return info;
}
private runTriggerInfo(info: TriggerExpressionInfo, name: string, value: any): void {
const expression = this[info.name];
if(!expression || info.isRunning || !info.canRun()) return;
const keys: any = {};
keys[name] = value;
if(!expression || info.isRunning || !info.canRun()) {
if(info.runSecondCheck(keys)) {
info.doComplete();
}
return;
}
if(!info.runner) {
info.runner = new ExpressionRunner(expression);
info.runner.onRunComplete = (res: any): void => {
Expand All @@ -557,9 +576,7 @@ export class Question extends SurveyElement<Question>
} else {
info.runner.expression = expression;
}
const keys: any = {};
keys[name] = value;
if(!new ProcessValue().isAnyKeyChanged(keys, info.runner.getVariables())) return;
if(!new ProcessValue().isAnyKeyChanged(keys, info.runner.getVariables()) && !info.runSecondCheck(keys)) return;
info.isRunning = true;
info.runner.run(this.getDataFilteredValues(), this.getDataFilteredProperties());
}
Expand Down
8 changes: 7 additions & 1 deletion tests/question_matrixdropdownbasetests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -886,7 +886,13 @@ QUnit.test("question.setValueIf, basic functionality", function (assert) {
q2.value = "edf";
assert.equal(q2.value, "edf", "value is set, #2");
q3.value = 5;
assert.equal(q2.value, "edf", "value is set, #3");
assert.equal(q2.value, 1 + 5, "value is set, #3");
q2.value = "klm";
assert.equal(q2.value, "klm", "value is set, #4");
q1.value = 2;
assert.equal(q2.value, "klm", "value is set, #5");
q3.value = 5;
assert.equal(q2.value, "klm", "value is set, #6");
});

QUnit.test("question.onHidingContent", function (assert) {
Expand Down
8 changes: 7 additions & 1 deletion tests/question_paneldynamic_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6425,5 +6425,11 @@ QUnit.test("question.setValueIf, basic functionality", function (assert) {
q2.value = "edf";
assert.equal(q2.value, "edf", "value is set, #2");
q3.value = 5;
assert.equal(q2.value, "edf", "value is stay, #3");
assert.equal(q2.value, 1 + 5, "value is set, #3");
q2.value = "klm";
assert.equal(q2.value, "klm", "value is set, #4");
q1.value = 2;
assert.equal(q2.value, "klm", "value is set, #5");
q3.value = 5;
assert.equal(q2.value, "klm", "value is set, #6");
});
71 changes: 56 additions & 15 deletions tests/surveyquestiontests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7401,20 +7401,10 @@ QUnit.test("question.resetValueIf and invisibleQuestions", function (assert) {
});
QUnit.test("question.setValueIf, basic functionality", function (assert) {
const survey = new SurveyModel({
elements: [{
"name": "q1",
"type": "text"
},
{
"name": "q2",
"type": "text",
"setValueIf": "{q1} = 1",
"setValueExpression": "{q1} + {q3}"
},
{
"name": "q3",
"type": "text"
}
elements: [
{ "name": "q1", "type": "text" },
{ "name": "q2", "type": "text", "setValueIf": "{q1} = 1", "setValueExpression": "{q1} + {q3}" },
{ "name": "q3", "type": "text" }
] });
const q1 = survey.getQuestionByName("q1");
const q2 = survey.getQuestionByName("q2");
Expand All @@ -7430,7 +7420,58 @@ QUnit.test("question.setValueIf, basic functionality", function (assert) {
q2.value = "edf";
assert.equal(q2.value, "edf", "value is set, #2");
q3.value = 5;
assert.equal(q2.value, "edf", "value is stay, #3");
assert.equal(q2.value, 1 + 5, "{q3} is changed");
q2.value = "klm";
assert.equal(q2.value, "klm", "value is set, #3");
q1.value = 2;
assert.equal(q2.value, "klm", "value is set, #4");
q3.value = 7;
assert.equal(q2.value, "klm", "value is set, #5");
});
QUnit.test("question.setValueIf, setValueExpression is empty", function (assert) {
const survey = new SurveyModel({
elements: [
{ "name": "q1", "type": "text" },
{ "name": "q2", "type": "text", "setValueIf": "{q1} = 1" },
{ "name": "q3", "type": "text" }
] });
const q1 = survey.getQuestionByName("q1");
const q2 = survey.getQuestionByName("q2");
const q3 = survey.getQuestionByName("q3");
q2.value = "abc";
q1.value = 2;
q3.value = 3;
assert.equal(q2.value, "abc", "value is set");
q1.value = 1;
assert.equal(q2.isEmpty(), true, "value is clear");
q2.value = "edf";
assert.equal(q2.value, "edf", "value is set, #2");
q3.value = 5;
assert.equal(q2.value, "edf", "value is keep, #3");
q1.value = 2;
assert.equal(q2.value, "edf", "value is keep, #3");
});
QUnit.test("question.setValueIf is empty, setValueExpression is not empty", function (assert) {
const survey = new SurveyModel({
elements: [
{ "name": "q1", "type": "text" },
{ "name": "q2", "type": "text", "setValueExpression": "{q1} + {q3}" },
{ "name": "q3", "type": "text" }
] });
const q1 = survey.getQuestionByName("q1");
const q2 = survey.getQuestionByName("q2");
const q3 = survey.getQuestionByName("q3");
assert.equal(q2.setValueExpression, "{q1} + {q3}", "Load from JSON, setValueExpression");
q2.value = "abc";
q1.value = 2;
q3.value = 3;
assert.equal(q2.value, 2 + 3, "value is set");
q2.value = "edf";
assert.equal(q2.value, "edf", "value is set, #2");
q3.value = 5;
assert.equal(q2.value, 2 + 5, "value is keep, #3");
q1.value = 3;
assert.equal(q2.value, 3 + 5, "value is keep, #4");
});

QUnit.test("question.isReady & async functions in expression", function (assert) {
Expand Down

0 comments on commit 95ecc0f

Please sign in to comment.