From 6cafc9eafa3599d74e75a00ed024083961a38dd6 Mon Sep 17 00:00:00 2001 From: Andrew Telnov Date: Sat, 26 Aug 2023 13:04:42 +0300 Subject: [PATCH] Fix issue with choices visibleIf in mutliple columns #6706 --- src/question_matrixdropdownbase.ts | 40 +++++++++---- src/question_matrixdropdowncolumn.ts | 35 +++++++++++- src/question_matrixdropdownrendered.ts | 2 +- tests/question_matrixdynamictests.ts | 79 ++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 15 deletions(-) diff --git a/src/question_matrixdropdownbase.ts b/src/question_matrixdropdownbase.ts index 31d948da8a..0631ff4ee1 100644 --- a/src/question_matrixdropdownbase.ts +++ b/src/question_matrixdropdownbase.ts @@ -1378,9 +1378,9 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel(); + let hasVisCell = false; + const rows = this.generatedVisibleRows; + for (let i = 0; i < rows.length; i++) { + const cell = rows[i].cells[column.index]; + const q = cell?.question; + if (!!q && q.isVisible) { hasVisCell = true; - break; + if(isMultipleColumnsVisibility) { + this.updateNewVisibleChoices(q, newVisibleChoices); + } else break; } } if (curVis != hasVisCell) { column.hasVisibleCell = hasVisCell; } + if(isMultipleColumnsVisibility) { + column.setVisibleChoicesInCell(newVisibleChoices); + if(!Helpers.isArraysEqual(curVisibleChoices, newVisibleChoices, true, false, false)) return true; + } return curVis != hasVisCell; } + private updateNewVisibleChoices(q: Question, dest: Array): void { + const choices = q.visibleChoices; + if(!Array.isArray(choices)) return; + for(let i = 0; i < choices.length; i ++) { + const ch = choices[i]; + if(dest.indexOf(ch.value) < 0) dest.push(ch.value); + } + } protected runTotalsCondition( values: HashTable, properties: HashTable - ) { + ): void { if (!this.generatedTotalRow) return; this.generatedTotalRow.runCondition( this.getRowConditionValues(values), diff --git a/src/question_matrixdropdowncolumn.ts b/src/question_matrixdropdowncolumn.ts index e37200d77b..51837a1b37 100644 --- a/src/question_matrixdropdowncolumn.ts +++ b/src/question_matrixdropdowncolumn.ts @@ -124,6 +124,7 @@ export class MatrixDropdownColumn extends Base private indexValue = -1; private _isVisible = true; private _hasVisibleCell = true; + private _visiblechoices: Array; constructor(name: string, title: string = null) { super(); @@ -209,16 +210,44 @@ export class MatrixDropdownColumn extends Base public get isVisible() { return this._isVisible; } - public setIsVisible(newVal: boolean) { + public setIsVisible(newVal: boolean): void { this._isVisible = newVal; } - public get hasVisibleCell() { + public get hasVisibleCell(): boolean { return this._hasVisibleCell; } public set hasVisibleCell(newVal: boolean) { this._hasVisibleCell = newVal; } - public get name() { + public getVisibleMultipleChoices(): Array { + const choices = this.templateQuestion.visibleChoices; + if(!Array.isArray(choices)) return []; + if(!Array.isArray(this._visiblechoices)) return choices; + const res = new Array(); + for(let i = 0; i < choices.length; i ++) { + const item = choices[i]; + if(this._visiblechoices.indexOf(item.value) > -1) res.push(item); + } + return res; + } + public get getVisibleChoicesInCell(): Array { + if(Array.isArray(this._visiblechoices)) return this._visiblechoices; + const res = this.templateQuestion.visibleChoices; + return Array.isArray(res) ? res : []; + } + public setVisibleChoicesInCell(val: Array): void { + this._visiblechoices = val; + } + public get isFilteredMultipleColumns(): boolean { + if(!this.showInMultipleColumns) return false; + const choices = this.templateQuestion.choices; + if(!Array.isArray(choices)) return false; + for(let i = 0; i < choices.length; i ++) { + if(choices[i].visibleIf) return true; + } + return false; + } + public get name(): string { return this.templateQuestion.name; } public set name(val: string) { diff --git a/src/question_matrixdropdownrendered.ts b/src/question_matrixdropdownrendered.ts index 539e1c4078..490e90eab3 100644 --- a/src/question_matrixdropdownrendered.ts +++ b/src/question_matrixdropdownrendered.ts @@ -936,7 +936,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { var choices = column.templateQuestion.choices; if (!!choices && Array.isArray(choices) && choices.length == 0) return this.matrix.choices; - choices = column.templateQuestion.visibleChoices; + choices = column.getVisibleMultipleChoices(); if (!choices || !Array.isArray(choices)) return null; return choices; } diff --git a/tests/question_matrixdynamictests.ts b/tests/question_matrixdynamictests.ts index 6d9a42a507..beb51e95e6 100644 --- a/tests/question_matrixdynamictests.ts +++ b/tests/question_matrixdynamictests.ts @@ -4686,6 +4686,85 @@ QUnit.test("showInMultipleColumns and hasOther properties, change in run-time in assert.equal(matrix.renderedTable.rows[0].cells.length, 2 + 1, "first row: 2 choices + hasOther"); assert.equal(matrix.renderedTable.headerRow.cells[2].locTitle.text, "Other (describe)", "Column text is correct"); }); +QUnit.test("showInMultipleColumns property, and visibleIf in choices", function (assert) { + const survey = new SurveyModel({ + elements: [ + { + type: "matrixdropdown", + name: "matrix", + columns: [ + { + name: "col1", + cellType: "text", + totalType: "sum", + }, + { + name: "col2", + cellType: "checkbox", + showInMultipleColumns: true, + hasNone: true, + choices: [ + { value: "A", visibleIf: "{val1} = 1" }, + { value: "B", visibleIf: "{val1} = 2" }, + { value: "C", visibleIf: "{val1} = 3" } + ] + } + ], + rows: ["row1", "row2"], + }, + ], + }); + const matrix = survey.getQuestionByName("matrix"); + const column = matrix.getColumnByName("col2"); + const choices = column.templateQuestion.visibleChoices; + assert.equal(choices.length, 4, "There are 4 choices"); + assert.equal(column.isFilteredMultipleColumns, true, "multiple column has visibleIf in choices"); + + let table = matrix.renderedTable; + let multipleChoices = column.getVisibleMultipleChoices(); + assert.equal(multipleChoices.length, 1, "One visible choice"); + assert.equal(multipleChoices[0].value, "none", "none is only visible"); + assert.equal(table.headerRow.cells.length, 1 + 1 + 1, "header: row value + 1 choices"); + assert.equal(table.rows[1].cells.length, 1 + 1 + 1, "first row: row value + 1 choices"); + assert.equal(table.headerRow.cells[2].locTitle.textOrHtml, "None", "Header None"); + assert.equal(table.rows[1].cells[2].choiceValue, "none", "none index in the first row"); + + survey.setValue("val1", 1); + table = matrix.renderedTable; + multipleChoices = column.getVisibleMultipleChoices(); + assert.equal(multipleChoices.length, 2, "Two visible choice"); + assert.equal(multipleChoices[0].value, "A", "A is visible"); + assert.equal(multipleChoices[1].value, "none", "none is visible"); + assert.equal(table.headerRow.cells.length, 1 + 1 + 2, "header: row value + 1 choices, #2"); + assert.equal(table.rows[1].cells.length, 1 + 1 + 2, "first row: row value + 1 choices, #2"); + assert.equal(table.headerRow.cells[2].locTitle.textOrHtml, "A", "Header A, #2"); + assert.equal(table.headerRow.cells[3].locTitle.textOrHtml, "None", "Header None, #2"); + assert.equal(table.rows[1].cells[2].choiceValue, "A", "none in the first row, #2"); + assert.equal(table.rows[1].cells[3].choiceValue, "none", "none in the first row, #2"); + + survey.setValue("val1", 3); + table = matrix.renderedTable; + multipleChoices = column.getVisibleMultipleChoices(); + assert.equal(multipleChoices.length, 2, "Two visible choice"); + assert.equal(multipleChoices[0].value, "C", "C is visible"); + assert.equal(multipleChoices[1].value, "none", "none is visible"); + assert.equal(table.headerRow.cells.length, 1 + 1 + 2, "header: row value + 1 choices, #3"); + assert.equal(table.rows[1].cells.length, 1 + 1 + 2, "first row: row value + 1 choices, #3"); + assert.equal(table.headerRow.cells[2].locTitle.textOrHtml, "C", "Header C, #3"); + assert.equal(table.headerRow.cells[3].locTitle.textOrHtml, "None", "Header None, #3"); + assert.equal(table.rows[1].cells[2].choiceValue, "C", "none in the first row, #3"); + assert.equal(table.rows[1].cells[3].choiceValue, "none", "none in the first row, #3"); + + survey.setValue("val1", 4); + table = matrix.renderedTable; + multipleChoices = column.getVisibleMultipleChoices(); + assert.equal(multipleChoices.length, 1, "Two visible choice"); + assert.equal(multipleChoices[0].value, "none", "none is visible"); + assert.equal(table.headerRow.cells.length, 1 + 1 + 1, "header: row value + 1 choices, #4"); + assert.equal(table.rows[1].cells.length, 1 + 1 + 1, "first row: row value + 1 choices, #4"); + assert.equal(table.headerRow.cells[2].locTitle.textOrHtml, "None", "Header None, #4"); + assert.equal(table.rows[1].cells[2].choiceValue, "none", "none in the first row, #4"); +}); QUnit.test( "showInMultipleColumns property + columnLayout = 'vertical'", function (assert) {