Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issue with choices visibleIf in mutliple columns #6706 #6805

Merged
merged 1 commit into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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