From 80b155aac146f0ccc808ce0f5b3ba58b0b61ef14 Mon Sep 17 00:00:00 2001
From: OlgaLarina <olga.larina.dev@gmail.com>
Date: Mon, 1 Jul 2024 18:00:45 +0300
Subject: [PATCH] work for #8450 TagBox - Prevoiusly selected options disappear
 when searching for a new value

---
 src/question_checkbox.ts       |  3 +-
 src/question_dropdown.ts       |  2 +-
 src/question_tagbox.ts         |  2 +-
 tests/question_tagbox_tests.ts | 64 +++++++++++++++++++++++++++++++++-
 4 files changed, 67 insertions(+), 4 deletions(-)

diff --git a/src/question_checkbox.ts b/src/question_checkbox.ts
index 755c74aa55..d4e43fa414 100644
--- a/src/question_checkbox.ts
+++ b/src/question_checkbox.ts
@@ -247,7 +247,8 @@ export class QuestionCheckboxModel extends QuestionCheckboxBase {
       this.updateSelectedItemValues();
     }
 
-    return this.validateItemValues(itemValues);
+    const validValues = this.validateItemValues(itemValues);
+    return validValues;
   }
   public get selectedItems(): Array<ItemValue> { return this.selectedChoices; }
   public get hasFilteredValue(): boolean { return !!this.valuePropertyName; }
diff --git a/src/question_dropdown.ts b/src/question_dropdown.ts
index 6e0c77d069..71ab3aa7f9 100644
--- a/src/question_dropdown.ts
+++ b/src/question_dropdown.ts
@@ -316,7 +316,7 @@ export class QuestionDropdownModel extends QuestionSelectBase {
     return super.hasUnknownValue(val, true, false);
   }
   protected getItemIfChoicesNotContainThisValue(value: any, text?: string): any {
-    if(this.choicesLazyLoadEnabled && !this.dropdownListModel.isAllDataLoaded) {
+    if (this.choicesLazyLoadEnabled) {
       return this.createItemValue(value, text);
     } else {
       return super.getItemIfChoicesNotContainThisValue(value, text);
diff --git a/src/question_tagbox.ts b/src/question_tagbox.ts
index f860c9dbb9..300a8e5d8c 100644
--- a/src/question_tagbox.ts
+++ b/src/question_tagbox.ts
@@ -199,7 +199,7 @@ export class QuestionTagboxModel extends QuestionCheckboxModel {
     }
   }
   protected getItemIfChoicesNotContainThisValue(value: any, text?: string): any {
-    if(this.choicesLazyLoadEnabled && !this.dropdownListModel?.isAllDataLoaded) {
+    if (this.choicesLazyLoadEnabled) {
       return this.createItemValue(value, text);
     } else {
       return super.getItemIfChoicesNotContainThisValue(value, text);
diff --git a/tests/question_tagbox_tests.ts b/tests/question_tagbox_tests.ts
index 5690b05df3..2759a9721c 100644
--- a/tests/question_tagbox_tests.ts
+++ b/tests/question_tagbox_tests.ts
@@ -327,7 +327,7 @@ const onChoicesLazyLoadCallbackTimeOut = 5;
 const callbackTimeOutDelta = 1;
 
 const callback = (_, opt) => {
-  const total = 70;
+  const total = opt.filter == "888" ? 17 : 70;
   setTimeout(() => {
     if (opt.skip + opt.take < total) {
       opt.setItems(getNumberArray(opt.skip + 1, opt.take, opt.filter), total);
@@ -1633,3 +1633,65 @@ QUnit.test("Create tag box from json, dropdownListModel instance", (assert) => {
   const question = <QuestionTagboxModel>survey.getAllQuestions()[0];
   assert.ok(question.dropdownListModel, "It is created");
 });
+
+QUnit.test("Prevoiusly selected options disappear", (assert) => {
+  const done1 = assert.async();
+  const done2 = assert.async();
+  const done3 = assert.async();
+  const done4 = assert.async();
+  const json = {
+    questions: [{
+      "type": "tagbox",
+      "name": "q1",
+      "defaultValue": [5],
+      "choicesLazyLoadEnabled": true,
+    }]
+  };
+  const survey = new SurveyModel(json);
+  survey.onChoicesLazyLoad.add(callback);
+  survey.onGetChoiceDisplayValue.add((sender, options) => {
+    if (options.question.name == "q1") {
+      options.setItems(options.values.map(item => ("DisplayText_" + item)));
+    }
+  });
+
+  const question = <QuestionTagboxModel>survey.getAllQuestions()[0];
+  const dropdownListModel = question.dropdownListModel;
+  const list: MultiSelectListModel = dropdownListModel.popupModel.contentComponentData.model as MultiSelectListModel;
+  assert.deepEqual(question.value, [5], "question value");
+  assert.equal(question.selectedItems.length, 1);
+  assert.equal(question.selectedChoices.length, 1);
+
+  question.dropdownListModel.popupModel.show();
+  setTimeout(() => {
+    dropdownListModel.inputStringRendered = "777";
+    assert.deepEqual(question.value, [5], "question value");
+    assert.equal(question.selectedItems.length, 1);
+    assert.equal(question.selectedChoices.length, 1);
+
+    setTimeout(() => {
+      list.onItemClick(list.actions[0]);
+      assert.deepEqual(question.value, [5, 777], "question value");
+      assert.equal(question.selectedItems.length, 2);
+      assert.equal(question.selectedChoices.length, 2);
+
+      setTimeout(() => {
+        dropdownListModel.inputStringRendered = "888";
+        assert.deepEqual(question.value, [5, 777], "question value");
+        assert.equal(question.selectedItems.length, 2);
+        assert.equal(question.selectedChoices.length, 2);
+
+        setTimeout(() => {
+          assert.deepEqual(question.value, [5, 777], "question value");
+          assert.equal(question.selectedItems.length, 2);
+          assert.equal(question.selectedChoices.length, 2);
+
+          done4();
+        }, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
+        done3();
+      }, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
+      done2();
+    }, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
+    done1();
+  }, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);
+});
\ No newline at end of file