Skip to content

Commit

Permalink
Fix issue with choices visibleIf in mutliple columns #6706 (#6805)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewtelnov committed Aug 26, 2023
1 parent 1663bef commit 8a700ce
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 15 deletions.
40 changes: 29 additions & 11 deletions src/question_matrixdropdownbase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1378,9 +1378,9 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel<Mat
private checkColumnsVisibility() {
var hasChanged = false;
for (var i = 0; i < this.visibleColumns.length; i++) {
if (!this.visibleColumns[i].visibleIf) continue;
hasChanged =
this.isColumnVisibilityChanged(this.visibleColumns[i]) || hasChanged;
const column = this.visibleColumns[i];
if (!column.visibleIf && !column.isFilteredMultipleColumns) continue;
hasChanged = this.isColumnVisibilityChanged(column) || hasChanged;
}
if (hasChanged) {
this.resetRenderedTable();
Expand All @@ -1402,25 +1402,43 @@ export class QuestionMatrixDropdownModelBase extends QuestionMatrixBaseModel<Mat
}
}
private isColumnVisibilityChanged(column: MatrixDropdownColumn): boolean {
var curVis = column.hasVisibleCell;
var hasVisCell = false;
var rows = this.generatedVisibleRows;
for (var i = 0; i < rows.length; i++) {
var cell = rows[i].cells[column.index];
if (!!cell && !!cell.question && cell.question.isVisible) {
const curVis = column.hasVisibleCell;
const isMultipleColumnsVisibility = column.isFilteredMultipleColumns;
const curVisibleChoices = isMultipleColumnsVisibility ? column.getVisibleChoicesInCell : [];
const newVisibleChoices = new Array<any>();
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<any>): 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<any>,
properties: HashTable<any>
) {
): void {
if (!this.generatedTotalRow) return;
this.generatedTotalRow.runCondition(
this.getRowConditionValues(values),
Expand Down
35 changes: 32 additions & 3 deletions src/question_matrixdropdowncolumn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export class MatrixDropdownColumn extends Base
private indexValue = -1;
private _isVisible = true;
private _hasVisibleCell = true;
private _visiblechoices: Array<any>;

constructor(name: string, title: string = null) {
super();
Expand Down Expand Up @@ -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<ItemValue> {
const choices = this.templateQuestion.visibleChoices;
if(!Array.isArray(choices)) return [];
if(!Array.isArray(this._visiblechoices)) return choices;
const res = new Array<ItemValue>();
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<any> {
if(Array.isArray(this._visiblechoices)) return this._visiblechoices;
const res = this.templateQuestion.visibleChoices;
return Array.isArray(res) ? res : [];
}
public setVisibleChoicesInCell(val: Array<any>): 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) {
Expand Down
2 changes: 1 addition & 1 deletion src/question_matrixdropdownrendered.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
79 changes: 79 additions & 0 deletions tests/question_matrixdynamictests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = <QuestionMatrixDropdownModel>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) {
Expand Down

0 comments on commit 8a700ce

Please sign in to comment.