From cdaf9b2f2b8393d644f91ec964f5caf3aef774cc Mon Sep 17 00:00:00 2001 From: OlgaLarina Date: Mon, 2 Dec 2024 15:51:55 +0300 Subject: [PATCH] resolve #9111 Dropdown with Lazy Loading - A list of items display duplicate entries --- packages/survey-core/src/dropdownListModel.ts | 12 ++-- .../tests/questionDropdownTests.ts | 57 +++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/packages/survey-core/src/dropdownListModel.ts b/packages/survey-core/src/dropdownListModel.ts index 95bf748c98..9ea4070f24 100644 --- a/packages/survey-core/src/dropdownListModel.ts +++ b/packages/survey-core/src/dropdownListModel.ts @@ -78,11 +78,8 @@ export class DropdownListModel extends Base { const isUpdate = (this.itemsSettings.skip + 1) < this.itemsSettings.totalCount; if (!this.itemsSettings.skip || isUpdate) { + this.resetTimer(); if (!!this.filterString && settings.dropdownSearchDelay > 0) { - if (!!this.timer) { - clearTimeout(this.timer); - this.timer = undefined; - } this.timer = setTimeout(() => { this.loadQuestionChoices(callbackAfterItemsLoaded); }, settings.dropdownSearchDelay); @@ -92,6 +89,13 @@ export class DropdownListModel extends Base { } } + private resetTimer(): void { + if (!!this.timer) { + clearTimeout(this.timer); + this.timer = undefined; + } + } + private updatePopupFocusFirstInputSelector() { this._popupModel.focusFirstInputSelector = this.focusFirstInputSelector; } diff --git a/packages/survey-core/tests/questionDropdownTests.ts b/packages/survey-core/tests/questionDropdownTests.ts index 00cdd60b79..d9b077df43 100644 --- a/packages/survey-core/tests/questionDropdownTests.ts +++ b/packages/survey-core/tests/questionDropdownTests.ts @@ -2118,4 +2118,61 @@ QUnit.test("Rapidly Changing Search Filter", (assert) => { }, callbackTimeOutDelta); done1(); }, callbackTimeOutDelta); +}); + +QUnit.test("Dropdown with Lazy Loading - A list of items display duplicate entries #9111", assert => { + const done1 = assert.async(); + const done2 = assert.async(); + const done3 = assert.async(); + const done4 = assert.async(); + const newValueDebouncedInputValue = onChoicesLazyLoadCallbackTimeOut; + const oldValueDebouncedInputValue = settings.dropdownSearchDelay; + settings.dropdownSearchDelay = newValueDebouncedInputValue; + + const json = { + questions: [{ "type": "dropdown", "name": "q1", "choicesLazyLoadEnabled": true }] + }; + const survey = new SurveyModel(json); + survey.onChoicesLazyLoad.add((_, opt) => { + setTimeout(() => { + opt.setItems(getNumberArray(0, 5, opt.filter), 5); + }, onChoicesLazyLoadCallbackTimeOut); + }); + + const question = survey.getAllQuestions()[0]; + const itemsSettings = question.dropdownListModel["itemsSettings"]; + + assert.equal(question.choicesLazyLoadEnabled, true); + assert.equal(question.choices.length, 0); + assert.equal(question.choices.length, 0, "question.choices.length #1"); + assert.equal(itemsSettings.items.length, 0, "itemsSettings.items.length #1"); + + question.dropdownListModel.popupModel.show(); + setTimeout(() => { + assert.equal(question.choices.length, 5, "question.choices.length #2"); + + question.dropdownListModel.filterString = "22"; + setTimeout(() => { + assert.equal(question.choices.length, 5, "question.choices.length #3"); + + question.dropdownListModel.filterString = "2"; + setTimeout(() => { + assert.equal(question.choices.length, 5, "question.choices.length #4"); + + question.dropdownListModel.filterString = ""; + setTimeout(() => { + assert.equal(question.choices.length, 5, "question.choices.length #5"); + + settings.dropdownSearchDelay = oldValueDebouncedInputValue; + done4(); + }, onChoicesLazyLoadCallbackTimeOut + newValueDebouncedInputValue + callbackTimeOutDelta); + + done3(); + }, callbackTimeOutDelta); + + done2(); + }, onChoicesLazyLoadCallbackTimeOut + newValueDebouncedInputValue + callbackTimeOutDelta); + + done1(); + }, onChoicesLazyLoadCallbackTimeOut + newValueDebouncedInputValue + callbackTimeOutDelta); }); \ No newline at end of file