Skip to content

Commit

Permalink
max selected choices not work tagbox with lazy loading (#7204)
Browse files Browse the repository at this point in the history
* maxSelectedChoices doesn't work correctly when tagbox with the lazy loading

* FIx unit tests

---------

Co-authored-by: OlgaLarina <[email protected]>
Co-authored-by: Andrew Telnov <[email protected]>
  • Loading branch information
3 people authored Oct 20, 2023
1 parent 6fc86c8 commit 400bded
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 5 deletions.
5 changes: 3 additions & 2 deletions src/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,8 +564,9 @@ export class Base {
!!this.arraysInfo &&
(!val || Array.isArray(val))
) {
if (this.isTwoValueEquals(oldValue, val)) return;
this.setArrayPropertyDirectly(name, val);
if (!this.isTwoValueEquals(oldValue, val)) {
this.setArrayPropertyDirectly(name, val);
}
} else {
this.setPropertyValueDirectly(name, val);
if (!this.isDisposedValue && !this.isTwoValueEquals(oldValue, val)) {
Expand Down
9 changes: 6 additions & 3 deletions src/question_baseselect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,15 +864,18 @@ export class QuestionSelectBase extends Question {
}
return res;
}
protected updateVisibleChoices() {
if (this.isLoadingFromJson) return;
protected updateVisibleChoices(): void {
if (this.isLoadingFromJson || this.isDisposed) return;
var newValue = new Array<ItemValue>();
var calcValue = this.calcVisibleChoices();
if (!calcValue) calcValue = [];
for (var i = 0; i < calcValue.length; i++) {
newValue.push(calcValue[i]);
}
this.setPropertyValue("visibleChoices", newValue);
const oldValue = this.visibleChoices;
if(!this.isTwoValueEquals(oldValue, newValue) || this.choicesLazyLoadEnabled) {
this.setArrayPropertyDirectly("visibleChoices", newValue);
}
}
private calcVisibleChoices(): Array<ItemValue> {
if (this.canUseFilteredChoices()) return this.getFilteredChoices();
Expand Down
127 changes: 127 additions & 0 deletions tests/question_tagbox_tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1320,3 +1320,130 @@ QUnit.test("question.showClearButton", assert => {
assert.equal(q.showClearButton, true, "Creator V2");
settings.supportCreatorV2 = false;
});
QUnit.test("lazy loading: maxSelectedChoices limit stops working if you clear the value", assert => {
const done1 = assert.async();
const done2 = assert.async();
const json = {
questions: [{
"type": "tagbox",
"name": "q1",
"defaultValue": [1],
"choicesLazyLoadEnabled": true,
"choicesLazyLoadPageSize": 30,
"maxSelectedChoices": 2
}]
};
const survey = new SurveyModel(json);
survey.onChoicesLazyLoad.add(callback);

const question = <QuestionTagboxModel>survey.getAllQuestions()[0];
const dropdownListModel = question.dropdownListModel;
const list: MultiSelectListModel = dropdownListModel.popupModel.contentComponentData.model as MultiSelectListModel;
assert.equal(question.choicesLazyLoadEnabled, true);
assert.equal(question.choices.length, 0);

question.dropdownListModel.popupModel.toggleVisibility();
setTimeout(() => {
assert.deepEqual(question.value, [1]);
assert.equal(question.choices.length, 30);
for(let index = 0; index < list.actions.length - 1; index++) {
assert.ok(list.actions[index].enabled, list.actions[index].id + " is enabled before clear");
}

list.onItemClick(list.actions[1]);
assert.deepEqual(question.value, [1, 2]);
assert.ok(list.actions[0].enabled, "action 1 is enabled before clear");
assert.ok(list.actions[1].enabled, "action 2 is enabled before clear");
for(let index = 2; index < list.actions.length - 1; index++) {
assert.notOk(list.actions[index].enabled, list.actions[index].id + " is disabled before clear");
}
question.dropdownListModel.popupModel.isVisible = false;
question.dropdownListModel.onClear({
keyCode: 0,
preventDefault: () => { },
stopPropagation: () => { }
});

question.dropdownListModel.popupModel.toggleVisibility();
setTimeout(() => {
assert.deepEqual(question.value, [], "question value is empty");
list.onItemClick(list.actions[0]);
assert.deepEqual(question.value, [1], "question value is [1]");

for(let index = 0; index < list.actions.length - 1; index++) {
assert.ok(list.actions[index].enabled, list.actions[index].id + " is enabled after clear");
}

list.onItemClick(list.actions[1]);
assert.deepEqual(question.value, [1, 2], "question value is [1, 2] after clear");
assert.ok(list.actions[0].enabled, "action 1 is enabled after clear");
assert.ok(list.actions[1].enabled, "action 2 is enabled after clear");
for(let index = 2; index < list.actions.length - 1; index++) {
assert.notOk(list.actions[index].enabled, list.actions[index].id + " is disabled after clear");
}

done2();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);

done1();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
});
QUnit.test("lazy loading & maxSelectedChoices: Items remains disabled when unselecting choices within a drop-down list", assert => {
const done1 = assert.async();
const done2 = assert.async();
const json = {
questions: [{
"type": "tagbox",
"name": "q1",
"defaultValue": [1],
"choicesLazyLoadEnabled": true,
"choicesLazyLoadPageSize": 30,
"maxSelectedChoices": 2
}]
};
const survey = new SurveyModel(json);
survey.onChoicesLazyLoad.add(callback);

const question = <QuestionTagboxModel>survey.getAllQuestions()[0];
const dropdownListModel = question.dropdownListModel;
const list: MultiSelectListModel = dropdownListModel.popupModel.contentComponentData.model as MultiSelectListModel;
assert.equal(question.choicesLazyLoadEnabled, true);
assert.equal(question.choices.length, 0);

question.dropdownListModel.popupModel.toggleVisibility();
setTimeout(() => {
assert.deepEqual(question.value, [1]);
assert.equal(question.choices.length, 30);
for(let index = 0; index < list.actions.length - 1; index++) {
assert.ok(list.actions[index].enabled, list.actions[index].id + " is enabled before unselecting choice");
}

list.onItemClick(list.actions[1]);
assert.deepEqual(question.value, [1, 2]);
assert.ok(list.actions[0].enabled, "action 1 is enabled before unselecting choice");
assert.ok(list.actions[1].enabled, "action 2 is enabled before unselecting choice");
for(let index = 2; index < list.actions.length - 1; index++) {
assert.notOk(list.actions[index].enabled, list.actions[index].id + " is disabled before unselecting choice");
}
question.dropdownListModel.popupModel.isVisible = false;
question.dropdownListModel.popupModel.toggleVisibility();
setTimeout(() => {
assert.deepEqual(question.value, [1, 2], "question value is [1, 2]");
assert.ok(list.actions[0].enabled, "action 1 is enabled");
assert.ok(list.actions[1].enabled, "action 2 is enabled");
for(let index = 2; index < list.actions.length - 1; index++) {
assert.notOk(list.actions[index].enabled, list.actions[index].id + " is disabled");
}

list.onItemClick(list.actions[1]);
assert.deepEqual(question.value, [1], "question value is [1]");
for(let index = 0; index < list.actions.length - 1; index++) {
assert.ok(list.actions[index].enabled, list.actions[index].id + " is enabled after unselecting choice");
}

done2();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);

done1();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
});

0 comments on commit 400bded

Please sign in to comment.