diff --git a/src/dropdownListModel.ts b/src/dropdownListModel.ts index b9435380cb..efd8ed6cef 100644 --- a/src/dropdownListModel.ts +++ b/src/dropdownListModel.ts @@ -36,7 +36,6 @@ export class DropdownListModel extends Base { } } private itemsSettings: { skip: number, take: number, totalCount: number, items: any[] } = { skip: 0, take: 0, totalCount: 0, items: [] }; - private isRunningLoadQuestionChoices = false; protected listModel: ListModel; protected popupCssClasses = "sv-single-select-list"; protected listModelFilterStringChanged = (newValue: string) => { @@ -58,14 +57,12 @@ export class DropdownListModel extends Base { this.question.choices = this.itemsSettings.items; } private loadQuestionChoices(callbackAfterItemsLoaded?: () => void) { - this.isRunningLoadQuestionChoices = true; this.question.survey.loadQuestionChoices({ question: this.question, filter: this.filterString, skip: this.itemsSettings.skip, take: this.itemsSettings.take, setItems: (items: Array, totalCount: number) => { - this.isRunningLoadQuestionChoices = false; this.setItems(items || [], totalCount || 0); this.popupRecalculatePosition(this.itemsSettings.skip === this.itemsSettings.take); if (!!callbackAfterItemsLoaded) { @@ -76,8 +73,6 @@ export class DropdownListModel extends Base { this.itemsSettings.skip += this.itemsSettings.take; } private updateQuestionChoices(callbackAfterItemsLoaded?: () => void): void { - if (this.isRunningLoadQuestionChoices) return; - const isUpdate = (this.itemsSettings.skip + 1) < this.itemsSettings.totalCount; if (!this.itemsSettings.skip || isUpdate) { diff --git a/tests/questionDropdownTests.ts b/tests/questionDropdownTests.ts index 6a6f46782a..e6c315be7d 100644 --- a/tests/questionDropdownTests.ts +++ b/tests/questionDropdownTests.ts @@ -2058,4 +2058,64 @@ QUnit.test("Dropdown choicesLazyLoadEnabled into matrixdynamic", function (asser done1(); }, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta); +}); + +QUnit.test("Rapidly Changing Search Filter", (assert) => { + const newValueDebouncedInputValue = 2 * onChoicesLazyLoadCallbackTimeOut; + const oldValueDebouncedInputValue = settings.dropdownSearchDelay; + settings.dropdownSearchDelay = newValueDebouncedInputValue; + + const done1 = assert.async(); + const done2 = assert.async(); + const done3 = assert.async(); + const done4 = assert.async(); + let filterValue = ""; + let filterValueLog = ""; + const json = { + questions: [{ + "type": "dropdown", + "name": "q1", + "choicesLazyLoadEnabled": true, + }] + }; + const survey = new SurveyModel(json); + survey.onChoicesLazyLoad.add((sender, option) => { + filterValueLog += (option.filter + "->"); + callback(sender, option); + }); + + const question = survey.getAllQuestions()[0]; + const dropdownListModel = question.dropdownListModel; + + filterValue = "1"; + dropdownListModel.inputStringRendered = filterValue; + setTimeout(() => { + assert.equal(question.choices.length, 0); + assert.equal(filterValueLog, "", "filter value 1"); + + filterValue += "2"; + dropdownListModel.inputStringRendered = filterValue; + setTimeout(() => { + assert.equal(question.choices.length, 0); + assert.equal(filterValueLog, "", "filter value 12"); + + filterValue += "3"; + dropdownListModel.inputStringRendered = filterValue; + setTimeout(() => { + assert.equal(filterValueLog, "123->", "filter value 123 #1"); + assert.equal(question.choices.length, 0); + + setTimeout(() => { + assert.equal(filterValueLog, "123->", "filter value 123 #2"); + assert.equal(question.choices.length, 25); + + settings.dropdownSearchDelay = oldValueDebouncedInputValue; + done4(); + }, callbackTimeOutDelta + onChoicesLazyLoadCallbackTimeOut); + done3(); + }, callbackTimeOutDelta + newValueDebouncedInputValue); + done2(); + }, callbackTimeOutDelta); + done1(); + }, callbackTimeOutDelta); }); \ No newline at end of file