From 1325b13fc25647d8237bc9f2ee50d1442e6ebbb0 Mon Sep 17 00:00:00 2001 From: Andrew Telnov Date: Mon, 20 Jan 2025 10:25:57 +0200 Subject: [PATCH] Support rate value visibleIf #9267 --- packages/survey-core/src/base.ts | 10 +++- packages/survey-core/src/question_rating.ts | 47 ++++++++++++++-- .../survey-core/tests/question_ratingtests.ts | 54 +++++++++++++++++-- 3 files changed, 101 insertions(+), 10 deletions(-) diff --git a/packages/survey-core/src/base.ts b/packages/survey-core/src/base.ts index 8fbb7215b9..e441bb644b 100644 --- a/packages/survey-core/src/base.ts +++ b/packages/survey-core/src/base.ts @@ -504,8 +504,14 @@ export class Base { if(!!calcFunc) { const newVal = calcFunc(); if(newVal !== undefined) { - this.setPropertyValueDirectly(name, newVal); - return newVal; + if(Array.isArray(newVal)) { + const array = this.createNewArray(name); + array.splice(0, 0, ...newVal); + return array; + } else { + this.setPropertyValueDirectly(name, newVal); + return newVal; + } } } const propDefaultValue = this.getDefaultPropertyValue(name); diff --git a/packages/survey-core/src/question_rating.ts b/packages/survey-core/src/question_rating.ts index 9cf56f2854..d319c88922 100644 --- a/packages/survey-core/src/question_rating.ts +++ b/packages/survey-core/src/question_rating.ts @@ -14,6 +14,7 @@ import { ISurveyImpl } from "./base-interfaces"; import { IsTouch } from "./utils/devices"; import { ITheme } from "./themes"; import { DomDocumentHelper } from "./global_variables_utils"; +import { HashTable } from "./helpers"; export class RenderedRatingItem extends Base { private onStringChangedCallback() { @@ -121,7 +122,6 @@ export class QuestionRatingModel extends Question { this.updateRateCount(); this.setIconsToRateValues(); } - private _syncPropertiesChanging: boolean = false; private registerSychProperties(names: Array, func: any) { this.registerFunctionOnPropertiesValueChanged(names, @@ -344,8 +344,40 @@ export class QuestionRatingModel extends Question { if (!this.useRateValues() && newValue !== undefined) this.autoGenerate = false; super.itemValuePropertyChanged(item, name, oldValue, newValue); } + protected runConditionCore(values: HashTable, properties: HashTable): void { + super.runConditionCore(values, properties); + this.runRateItesmCondition(values, properties); + } + protected runRateItesmCondition(values: HashTable, properties: HashTable): void { + if(!this.useRateValues()) return; + let isChanged = false; + if(this.survey?.areInvisibleElementsShowing) { + this.rateValues.forEach(item => { + isChanged = isChanged || !item.isVisible; + item.setIsVisible(item, true); + }); + } else { + isChanged = ItemValue.runConditionsForItems(this.rateValues, undefined, undefined, values, properties, true); + } + if(isChanged) { + this.resetRenderedItems(); + if(!this.isEmpty() && !this.isReadOnly) { + const item = ItemValue.getItemByValue(this.rateValues, this.value); + if(item && !item.isVisible) { + this.clearValue(); + } + } + } + } private getRateValuesCore(): Array { - return this.useRateValues() ? this.rateValues : this.createRateValues(); + if(!this.useRateValues()) return this.createRateValues(); + const items = new Array(); + this.rateValues.forEach(item => { + if(item.isVisible) { + items.push(item); + } + }); + return items; } private calculateRateValues(): Array { let rateValues = this.getRateValuesCore(); @@ -355,7 +387,7 @@ export class QuestionRatingModel extends Question { private calculateRenderedRateItems() : Array { const rateValues = this.calculateRateValues(); return rateValues.map((v, i) => { - let renderedItem = null; + let renderedItem: RenderedRatingItem = null; if (this.displayRateDescriptionsAsExtremeItems) { if (i == 0) renderedItem = new RenderedRatingItem(v, this.minRateDescription && this.locMinRateDescription || v.locText); if (i == rateValues.length - 1) renderedItem = new RenderedRatingItem(v, this.maxRateDescription && this.locMaxRateDescription || v.locText); @@ -368,13 +400,18 @@ export class QuestionRatingModel extends Question { const rateValues = this.calculateRateValues(); return rateValues.map((i, idx) => this.getRatingItemValue(i, idx)); } + private iCounter = 0; private resetRenderedItems() { if (this.autoGenerate) { const rateValues = this.getRateValuesCore(); this.rateMax = rateValues[rateValues.length - 1].value; } - this.resetPropertyValue("renderedRateItems"); - this.resetPropertyValue("visibleChoices"); + if(Array.isArray(this.getPropertyValueWithoutDefault("renderedRateItems"))) { + this.setArrayPropertyDirectly("renderedRateItems", this.calculateRenderedRateItems()); + } + if(Array.isArray(this.getPropertyValueWithoutDefault("visibleChoices"))) { + this.setArrayPropertyDirectly("visibleChoices", this.calculateVisibleChoices); + } } public get renderedRateItems(): Array { return this.getPropertyValue("renderedRateItems", undefined, () => this.calculateRenderedRateItems()); diff --git a/packages/survey-core/tests/question_ratingtests.ts b/packages/survey-core/tests/question_ratingtests.ts index 17eac5ee8e..5d0499cb55 100644 --- a/packages/survey-core/tests/question_ratingtests.ts +++ b/packages/survey-core/tests/question_ratingtests.ts @@ -304,10 +304,13 @@ QUnit.test("Check rateValues on text change", (assert) => { const survey = new SurveyModel(json); const q1 = survey.getQuestionByName("q1"); assert.equal(q1.rateValues.length, 0); - var oldRendered = q1.renderedRateValues; + let oldRendered = q1.renderedRateItems; q1.visibleRateValues[0].text = "abc"; assert.equal(q1.rateValues.length, 5); - assert.equal(q1.renderedRateValues, oldRendered, "renderedRateValues is not cloned"); + assert.strictEqual(q1.renderedRateItems, oldRendered, "renderedRateItems is cloned"); + oldRendered = q1.renderedRateItems; + q1.visibleRateValues[1].text = "abc"; + assert.strictEqual(q1.renderedRateItems, oldRendered, "renderedRateItems is not cloned"); }); QUnit.test("Check cssClasses update when dropdownListModel is set", (assert) => { var json = { @@ -1763,4 +1766,49 @@ QUnit.test("Check dropdown rating text, #8953", function (assert) { }); const question = survey.getAllQuestions()[0]; assert.deepEqual(question.visibleChoices.map(c => c.text), ["Label0", "Label1"]); -}); \ No newline at end of file +}); +QUnit.test("Ranking: items visibleIf and value, Bug#5959", function(assert) { + var survey = new SurveyModel({ + elements: [ + { type: "checkbox", name: "q1", choices: [1, 2] }, + { + type: "rating", + name: "q2", + rateValues: [ + { value: "a", visibleIf: "{q1} contains 1" }, + { value: "b", visibleIf: "{q1} contains 1" }, + { value: "c", visibleIf: "{q1} contains 2" }, + { value: "d", visibleIf: "{q1} contains 2" }, + { value: "e", visibleIf: "{q1} contains 1" }, + ] + } + ] + }); + const q1 = survey.getQuestionByName("q1"); + const q2 = survey.getQuestionByName("q2"); + assert.equal(q2.visibleRateValues.length, 0, "visibleRateValues #1"); + assert.equal(q2.renderedRateItems.length, 0, "renderedRateItems #1"); + q1.value = [1]; + assert.equal(q2.visibleRateValues.length, 3, "visibleRateValues #2"); + assert.equal(q2.renderedRateItems.length, 3, "renderedRateItems #2"); + q1.value = [2]; + assert.equal(q2.visibleRateValues.length, 2, "visibleRateValues #3"); + assert.equal(q2.renderedRateItems.length, 2, "renderedRateItems #3"); + q1.value = [1, 2]; + assert.equal(q2.visibleRateValues.length, 5, "visibleRateValues #4"); + assert.equal(q2.renderedRateItems.length, 5, "renderedRateItems #4"); + q1.value = []; + assert.equal(q2.visibleRateValues.length, 0, "visibleRateValues #5"); + assert.equal(q2.renderedRateItems.length, 0, "renderedRateItems #5 "); + survey.showInvisibleElements = true; + assert.equal(q2.renderedRateItems.length, 5, "renderedRateItems #6"); + survey.showInvisibleElements = false; + assert.equal(q2.renderedRateItems.length, 0, "renderedRateItems #7"); + q1.value = [1]; + assert.equal(q2.renderedRateItems.length, 3, "renderedRateItems #8"); + q2.value = "b"; + assert.deepEqual(q2.value, "b", "value set correctly, #8"); + q1.value = [2]; + assert.equal(q2.renderedRateItems.length, 2, "renderedRateItems #9"); + assert.deepEqual(q2.isEmpty(), true, "value is reset, #9"); +});