diff --git a/src/question_matrixdropdownbase.ts b/src/question_matrixdropdownbase.ts index c84938277d..d2e95b6964 100644 --- a/src/question_matrixdropdownbase.ts +++ b/src/question_matrixdropdownbase.ts @@ -7,10 +7,8 @@ import { IElement, IQuestion, ISurveyData, ISurvey, ISurveyImpl, ITextProcessor, import { SurveyElement } from "./survey-element"; import { TextPreProcessorValue, QuestionTextProcessor } from "./textPreProcessor"; import { ItemValue } from "./itemvalue"; -import { surveyLocalization } from "./surveyStrings"; import { QuestionFactory } from "./questionfactory"; import { ILocalizableOwner, LocalizableString } from "./localizablestring"; -import { getCurrecyCodes } from "./question_expression"; import { FunctionFactory } from "./functionsfactory"; import { PanelModel } from "./panel"; import { settings } from "./settings"; @@ -18,7 +16,7 @@ import { KeyDuplicationError } from "./error"; import { SurveyModel } from "./survey"; import { SurveyError } from "./survey-error"; import { CssClassBuilder } from "./utils/cssClassBuilder"; -import { MatrixDropdownColumn } from "./question_matrixdropdowncolumn"; +import { IMatrixColumnOwner, MatrixDropdownColumn } from "./question_matrixdropdowncolumn"; import { QuestionMatrixDropdownRenderedCell, QuestionMatrixDropdownRenderedRow, QuestionMatrixDropdownRenderedTable } from "./question_matrixdropdownrendered"; export interface IMatrixDropdownData { @@ -681,7 +679,6 @@ implements ISurveyData, ISurveyImpl, ILocalizableOwner { var columns = this.data.columns; for (var i = 0; i < columns.length; i++) { var column = columns[i]; - if (!column.isVisible) continue; var cell = this.createCell(column); this.cells.push(cell); var cellValue = this.getCellValue(value, column.name); @@ -783,7 +780,7 @@ export class MatrixDropdownTotalRowModel extends MatrixDropdownRowModelBase { /** * A base class for the [QuestionMatrixDropdownModel](https://surveyjs.io/form-library/documentation/questionmatrixdropdownmodel) and [QuestionMatrixDynamicModel](https://surveyjs.io/form-library/documentation/questionmatrixdynamicmodel) classes. */ -export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel implements IMatrixDropdownData { +export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel implements IMatrixDropdownData, IMatrixColumnOwner { public static get defaultCellType() { return settings.matrix.defaultCellType; } @@ -1258,11 +1255,16 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel, properties: HashTable - ) { + ): void { if (!this.generatedVisibleRows) return; var newValues = this.getRowConditionValues(values); var rows = this.generatedVisibleRows; @@ -1375,7 +1377,8 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel(); @@ -1418,14 +1421,12 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel): void { const choices = q.visibleChoices; diff --git a/src/question_matrixdropdowncolumn.ts b/src/question_matrixdropdowncolumn.ts index 51837a1b37..5b6468fa27 100644 --- a/src/question_matrixdropdowncolumn.ts +++ b/src/question_matrixdropdowncolumn.ts @@ -27,6 +27,7 @@ export interface IMatrixColumnOwner extends ILocalizableOwner { oldValue: any ): void; onShowInMultipleColumnsChanged(column: MatrixDropdownColumn): void; + onColumnVisibilityChanged(column: MatrixDropdownColumn): void; getCellType(): string; getCustomCellType(column: MatrixDropdownColumn, row: MatrixDropdownRowModelBase, cellType: string): string; onColumnCellTypeChanged(column: MatrixDropdownColumn): void; @@ -122,7 +123,6 @@ export class MatrixDropdownColumn extends Base private templateQuestionValue: Question; private colOwnerValue: IMatrixColumnOwner = null; private indexValue = -1; - private _isVisible = true; private _hasVisibleCell = true; private _visiblechoices: Array; @@ -131,6 +131,7 @@ export class MatrixDropdownColumn extends Base this.createLocalizableString("totalFormat", this); this.createLocalizableString("cellHint", this); this.registerPropertyChangedHandlers(["showInMultipleColumns"], () => { this.doShowInMultipleColumnsChanged(); }); + this.registerPropertyChangedHandlers(["visible"], () => { this.doColumnVisibilityChanged(); }); this.updateTemplateQuestion(); this.name = name; if (title) { @@ -201,17 +202,23 @@ export class MatrixDropdownColumn extends Base this.colOwner.onColumnCellTypeChanged(this); } } - public get templateQuestion() { + public get templateQuestion(): Question { return this.templateQuestionValue; } public get value() { return this.templateQuestion.name; } - public get isVisible() { - return this._isVisible; + //For filtering columns + public get isVisible(): boolean { + return true; } - public setIsVisible(newVal: boolean): void { - this._isVisible = newVal; + public get isColumnVisible(): boolean { + if(this.isDesignMode) return true; + return this.visible && this.hasVisibleCell; + } + public get visible(): boolean { return this.getPropertyValue("visible"); } + public set visible(val: boolean) { + this.setPropertyValue("visible", val); } public get hasVisibleCell(): boolean { return this._hasVisibleCell; @@ -616,14 +623,19 @@ export class MatrixDropdownColumn extends Base } } - private doShowInMultipleColumnsChanged() { - if (this.colOwner != null && !this.isLoadingFromJson) { + private doShowInMultipleColumnsChanged(): void { + if (this.colOwner != null) { this.colOwner.onShowInMultipleColumnsChanged(this); } if (this.templateQuestion) { this.templateQuestion.autoOtherMode = this.isShowInMultipleColumns; } } + private doColumnVisibilityChanged(): void { + if (this.colOwner != null && !this.isDesignMode) { + this.colOwner.onColumnVisibilityChanged(this); + } + } private getProperties(curCellType: string): Array { return Serializer.getDynamicPropertiesByObj(this, curCellType); } @@ -710,6 +722,7 @@ Serializer.addClass( } }, "width", + { name: "visible:switch", default: true, overridingProperty: "visibleIf" }, "visibleIf:condition", "enableIf:condition", "requiredIf:condition", diff --git a/src/question_matrixdropdownrendered.ts b/src/question_matrixdropdownrendered.ts index 490e90eab3..9e90227500 100644 --- a/src/question_matrixdropdownrendered.ts +++ b/src/question_matrixdropdownrendered.ts @@ -408,7 +408,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { if (this.matrix.isColumnLayoutHorizontal) { for (var i = 0; i < this.matrix.visibleColumns.length; i++) { var column = this.matrix.visibleColumns[i]; - if (!column.hasVisibleCell) continue; + if (!column.isColumnVisible) continue; if (this.matrix.IsMultiplyColumn(column)) { this.createMutlipleColumnsHeader(column); } else { @@ -450,7 +450,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { var cells = this.matrix.visibleTotalRow.cells; for (var i = 0; i < cells.length; i++) { var cell = cells[i]; - if (!cell.column.hasVisibleCell) continue; + if (!cell.column.isColumnVisible) continue; if (this.matrix.IsMultiplyColumn(cell.column)) { this.createMutlipleColumnsFooter(this.footerRow, cell); } else { @@ -686,7 +686,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { } for (var i = 0; i < row.cells.length; i++) { let cell = row.cells[i]; - if (!cell.column.hasVisibleCell) continue; + if (!cell.column.isColumnVisible) continue; if (this.matrix.IsMultiplyColumn(cell.column)) { this.createMutlipleEditCells(res, cell); } else { @@ -762,7 +762,7 @@ export class QuestionMatrixDropdownRenderedTable extends Base { var renderedRows = []; for (var i = 0; i < columns.length; i++) { var col = columns[i]; - if (col.isVisible && col.hasVisibleCell) { + if (col.isColumnVisible) { if (this.matrix.IsMultiplyColumn(col)) { this.createMutlipleVerticalRows(renderedRows, col, i); } else { diff --git a/tests/jsonobjecttests.ts b/tests/jsonobjecttests.ts index bac1a2d9bd..0ce8ffd81e 100644 --- a/tests/jsonobjecttests.ts +++ b/tests/jsonobjecttests.ts @@ -2980,4 +2980,12 @@ QUnit.test("multipletextitem, name property should be required and unique", func const prop = Serializer.findProperty("multipletextitem", "name"); assert.equal(prop.isRequired, true, "name property is required"); assert.equal(prop.isUnique, true, "name property is unique"); +}); +QUnit.test("load matrix column, visible property", function (assert) { + const matrix = new QuestionMatrixDynamicModel("q1"); + const column = matrix.addColumn("col1"); + assert.equal(column.visible, true, "It is visible by default"); + column.fromJSON({ title: "column1", visible: false }); + assert.equal(column.title, "column1", "set column title correctly"); + assert.equal(column.visible, false, "column.visible is false"); }); \ No newline at end of file diff --git a/tests/question_matrixdropdownbasetests.ts b/tests/question_matrixdropdownbasetests.ts index f96dd77d4f..5c4b5cc056 100644 --- a/tests/question_matrixdropdownbasetests.ts +++ b/tests/question_matrixdropdownbasetests.ts @@ -635,4 +635,69 @@ QUnit.test("Set incorrect value into matrix dropdown", function (assert) { assert.notOk(matrix.value, "matrix value is empty, #2"); survey.data = { matrix: { row1: 1 } }; assert.equal(matrix.isEmpty(), false, "Set correct value"); +}); +QUnit.test("column.visible property", function (assert) { + const survey = new SurveyModel({ + elements: [ + { + type: "matrixdropdown", + name: "matrix", + columns: [ + { name: "col1", cellType: "text" }, + { name: "col2", cellType: "text", visible: false }, + { name: "col3", cellType: "text" } + ], + rows: ["row1"], + }, + ], + }); + const matrix = survey.getQuestionByName("matrix"); + assert.equal(matrix.columns[0].visible, true, "The default column.visible is true"); + assert.equal(matrix.columns[1].visible, false, "The second column.visible is false"); + let table = matrix.renderedTable; + assert.equal(table.headerRow.cells.length, 1 + 2, "Header: One column is invisible, #1"); + assert.equal(table.rows[1].cells.length, 1 + 2, "Row: One column is invisible, #1"); + assert.equal(table.headerRow.cells[2].headers, "col3", "The second column is col3, #1"); + matrix.columns[1].visible = true; + assert.notStrictEqual(table, matrix.renderedTable); + table = matrix.renderedTable; + assert.equal(table.headerRow.cells.length, 1 + 3, "Header: All columns are visible, #2"); + assert.equal(table.rows[1].cells.length, 1 + 3, "Row: All columns are visible, #2"); + assert.equal(table.headerRow.cells[2].headers, "col2", "The second column is col2, #2"); + matrix.columns[2].visible = false; + table = matrix.renderedTable; + assert.equal(table.headerRow.cells.length, 1 + 2, "Header: the last column is invisible, #3"); + assert.equal(table.rows[1].cells.length, 1 + 2, "Row: the last column is invisible, #3"); + assert.equal(table.headerRow.cells[2].headers, "col2", "The last column is col2, #3"); +}); +QUnit.test("column.visible property and design time", function (assert) { + const survey = new SurveyModel(); + survey.setDesignMode(true); + survey.fromJSON({ + elements: [ + { + type: "matrixdropdown", + name: "matrix", + columns: [ + { name: "col1", cellType: "text" }, + { name: "col2", cellType: "text", visible: false }, + { name: "col3", cellType: "text" } + ], + rows: ["row1"], + }, + ], + }); + const matrix = survey.getQuestionByName("matrix"); + assert.equal(matrix.columns[0].visible, true, "Column is visible by default"); + assert.equal(matrix.columns[1].visible, false, "visible property is false"); + assert.equal(matrix.columns[1].hasVisibleCell, true, "It is visible"); + let table = matrix.renderedTable; + assert.equal(table.headerRow.cells.length, 1 + 3, "Header: One column is invisible, but it is visible in design-time, #1"); + assert.equal(table.rows[1].cells.length, 1 + 3, "Row: One column is invisible, but it is visible in design-time, #1"); + assert.equal(table.headerRow.cells[3].headers, "col3", "The last column is col3, #1"); + matrix.columns[2].visible = false; + table = matrix.renderedTable; + assert.equal(table.headerRow.cells.length, 1 + 3, "Header: Two columns are invisible, but it is visible in design-time, #2"); + assert.equal(table.rows[1].cells.length, 1 + 3, "Row: Two columns are invisible, but it is visible in design-time, #2"); + assert.equal(table.headerRow.cells[3].headers, "col3", "The last column is col3, #2"); }); \ No newline at end of file diff --git a/tests/question_matrixdynamictests.ts b/tests/question_matrixdynamictests.ts index beb51e95e6..825894d207 100644 --- a/tests/question_matrixdynamictests.ts +++ b/tests/question_matrixdynamictests.ts @@ -1097,11 +1097,14 @@ QUnit.test("Matrixdynamic column.visibleIf", function (assert) { question.columns.push(new MatrixDropdownColumn("column1")); question.columns.push(new MatrixDropdownColumn("column2")); question.columns.push(new MatrixDropdownColumn("column3")); - question.columns[0]["choices"] = [1, 2, 3]; - question.columns[1]["choices"] = [4, 5]; - question.columns[2]["choices"] = [7, 8, 9, 10]; - question.columns[2].isRequired = true; - + const columns = question.columns; + columns[0]["choices"] = [1, 2, 3]; + columns[1]["choices"] = [4, 5]; + columns[2]["choices"] = [7, 8, 9, 10]; + columns[2].isRequired = true; + assert.equal(columns[0].visible, true, "columns[0].visible"); + assert.equal(columns[1].visible, true, "columns[1].visible"); + assert.equal(columns[2].visible, true, "columns[2].visible"); question.columns[1].visibleIf = "{row.column1} = 2"; question.columns[2].visibleIf = "{a} = 5"; @@ -1327,6 +1330,7 @@ QUnit.test( "The second column is invisible" ); survey.setValue("q2", 1); + let table = matrix.renderedTable; assert.equal( matrix.columns[0].hasVisibleCell, true, @@ -1362,6 +1366,7 @@ QUnit.test( "The second column is invisible now" ); survey.setValue("q2", 2); + table = matrix.renderedTable; assert.equal( matrix.columns[0].hasVisibleCell, false, @@ -7955,10 +7960,15 @@ QUnit.test("Summary doesn't work correctly if there is invisible column and clea clearInvisibleValues: "onHiddenContainer" }); const matrix = survey.getAllQuestions()[0]; + const rows = matrix.visibleRows; + assert.equal(rows.length, 2, "two rows"); + assert.equal(rows[0].cells.length, 4, "row[0].cells.length = 4"); + assert.equal(rows[1].cells.length, 4, "row[1].cells.length = 4"); matrix.visibleRows[0].cells[0].question.value = 1; matrix.visibleRows[0].cells[1].question.value = 2; matrix.visibleRows[1].cells[0].question.value = 3; matrix.visibleRows[1].cells[1].question.value = 4; + assert.equal(matrix.visibleTotalRow.cells.length, 4, "There are 4 cells"); assert.equal(matrix.visibleTotalRow.cells[2].value, 1 + 2 + 3 + 4, "summary calculated correctly"); }); QUnit.test("Set empty string to expression with empty total type", function (assert) {