Skip to content

Commit

Permalink
resolve #8177 Dropdown With Lazy Loading Within a matrix dynamic does…
Browse files Browse the repository at this point in the history
…n't display search results on Mobile (#8190)

Co-authored-by: OlgaLarina <olga.larina.dev@gmail.com>
  • Loading branch information
OlgaLarina and OlgaLarina committed Apr 27, 2024
1 parent a737939 commit 7a88d2a
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 16 deletions.
4 changes: 2 additions & 2 deletions src/actions/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ export function createDropdownActionModelAdvanced(actionOptions: IAction, listOp
innerPopupModel.toggleVisibility();
},
listOptions.allowSelection,
listOptions.selectedItem,
listOptions.onFilterStringChangedCallback
listOptions.selectedItem
);
listModel.locOwner = locOwner;
listModel.setOnFilterStringChangedCallback(listOptions.onFilterStringChangedCallback);
const innerPopupModel: PopupModel = new PopupModel("sv-list", { model: listModel }, popupOptions?.verticalPosition, popupOptions?.horizontalPosition, popupOptions?.showPointer, popupOptions?.isModal, popupOptions?.onCancel, popupOptions?.onApply, popupOptions?.onHide, popupOptions?.onShow, popupOptions?.cssClass, popupOptions?.title, () => {
listModel.dispose();
});
Expand Down
11 changes: 7 additions & 4 deletions src/dropdownListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export class DropdownListModel extends Base {
}
if (option.isVisible && this.question.choicesLazyLoadEnabled) {
this.listModel.actions = [];
this.resetItemsSettings();
this.updateQuestionChoices();
}

Expand Down Expand Up @@ -177,7 +178,7 @@ export class DropdownListModel extends Base {
this.popupModel.isVisible = false;
};
}
const res = new ListModel<ItemValue>(visibleItems, _onSelectionChanged, false, undefined, this.question.choicesLazyLoadEnabled ? this.listModelFilterStringChanged : undefined, this.listElementId);
const res = new ListModel<ItemValue>(visibleItems, _onSelectionChanged, false, undefined, this.listElementId);
this.setOnTextSearchCallbackForListModel(res);
res.renderElements = false;
res.forceShowFilter = true;
Expand Down Expand Up @@ -364,6 +365,7 @@ export class DropdownListModel extends Base {

this.listModel = this.createListModel();
this.updateAfterListModelCreated(this.listModel);
this.setChoicesLazyLoadEnabled(this.question.choicesLazyLoadEnabled);
this.setSearchEnabled(this.question.searchEnabled);
this.setTextWrapEnabled(this.question.textWrapEnabled);
this.createPopup();
Expand Down Expand Up @@ -392,6 +394,10 @@ export class DropdownListModel extends Base {
this.searchEnabled = newValue;
}

public setChoicesLazyLoadEnabled(newValue: boolean): void {
this.listModel.setOnFilterStringChangedCallback(newValue ? this.listModelFilterStringChanged : undefined);
}

public updateItems(): void {
this.listModel.setItems(this.getAvailableItems());
}
Expand All @@ -412,9 +418,6 @@ export class DropdownListModel extends Base {
if (options.name == "value") {
this.showInputFieldComponent = this.question.showInputFieldComponent;
}
if(options.name == "choicesLazyLoadEnabled" && options.newValue) {
this.listModel.setOnFilterStringChangedCallback(this.listModelFilterStringChanged);
}
if(options.name == "textWrapEnabled") {
this.setTextWrapEnabled(options.newValue);
}
Expand Down
2 changes: 1 addition & 1 deletion src/dropdownMultiSelectListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export class DropdownMultiSelectListModel extends DropdownListModel {
}
};
}
const res = new MultiSelectListModel<ItemValue>(visibleItems, _onSelectionChanged, false, undefined, this.question.choicesLazyLoadEnabled ? this.listModelFilterStringChanged : undefined, this.listElementId);
const res = new MultiSelectListModel<ItemValue>(visibleItems, _onSelectionChanged, false, undefined, this.listElementId);
res.actions.forEach(a => a.disableTabStop = true);
this.setOnTextSearchCallbackForListModel(res);
res.forceShowFilter = true;
Expand Down
6 changes: 3 additions & 3 deletions src/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface IListModel {
export class ListModel<T extends BaseAction = Action> extends ActionContainer<T> {
private listContainerHtmlElement: HTMLElement;
private loadingIndicatorValue: T;
private onFilterStringChangedCallback?: (text: string) => void;

@property({
defaultValue: true,
Expand Down Expand Up @@ -107,18 +108,17 @@ export class ListModel<T extends BaseAction = Action> extends ActionContainer<T>
public onSelectionChanged: (item: T, ...params: any[]) => void,
public allowSelection: boolean,
selectedItem?: IAction,
private onFilterStringChangedCallback?: (text: string) => void,
public elementId?: string
) {
super();
this.setItems(items);
this.selectedItem = selectedItem;
}
private onTextSearchCallback: (item: T, textToSearch: string) => boolean;
public setOnFilterStringChangedCallback(callback: (text: string) => void) {
public setOnFilterStringChangedCallback(callback: (text: string) => void): void {
this.onFilterStringChangedCallback = callback;
}
public setOnTextSearchCallback(callback: (item: T, textToSearch: string) => boolean) {
public setOnTextSearchCallback(callback: (item: T, textToSearch: string) => boolean): void {
this.onTextSearchCallback = callback;
}
public setItems(items: Array<IAction>, sortByVisibleIndex = true): void {
Expand Down
4 changes: 2 additions & 2 deletions src/multiSelectListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export class MultiSelectListModel<T extends BaseAction = Action> extends ListMod
});
}

constructor(items: Array<IAction>, onSelectionChanged: (item: T, status: string) => void, allowSelection: boolean, selectedItems?: Array<IAction>, onFilterStringChangedCallback?: (text: string) => void, elementId?: string) {
super(items, onSelectionChanged, allowSelection, undefined, onFilterStringChangedCallback, elementId);
constructor(items: Array<IAction>, onSelectionChanged: (item: T, status: string) => void, allowSelection: boolean, selectedItems?: Array<IAction>, elementId?: string) {
super(items, onSelectionChanged, allowSelection, undefined, elementId);
this.setSelectedItems(selectedItems || []);
}

Expand Down
8 changes: 7 additions & 1 deletion src/question_dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,13 @@ export class QuestionDropdownModel extends QuestionSelectBase {
* @see choicesLazyLoadPageSize
* @see SurveyModel.onChoicesLazyLoad
*/
@property() choicesLazyLoadEnabled: boolean;
@property({
onSet: (newValue: boolean, target: QuestionDropdownModel) => {
if (!!target.dropdownListModel) {
target.dropdownListModel.setChoicesLazyLoadEnabled(newValue);
}
}
}) choicesLazyLoadEnabled: boolean;
/**
* Specifies the number of choice items to load at a time when choices are loaded on demand.
* @see choicesLazyLoadEnabled
Expand Down
8 changes: 7 additions & 1 deletion src/question_tagbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,13 @@ export class QuestionTagboxModel extends QuestionCheckboxModel {
* @see choicesLazyLoadPageSize
* @see SurveyModel.onChoicesLazyLoad
*/
@property() choicesLazyLoadEnabled: boolean;
@property({
onSet: (newValue: boolean, target: QuestionTagboxModel) => {
if (!!target.dropdownListModel) {
target.dropdownListModel.setChoicesLazyLoadEnabled(newValue);
}
}
}) choicesLazyLoadEnabled: boolean;
/**
* Specifies the number of choice items to load at a time when choices are loaded on demand.
* @see choicesLazyLoadEnabled
Expand Down
6 changes: 4 additions & 2 deletions tests/listModelTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ QUnit.test("ListModel custom onFilter", assert => {
new Action({ id: "test7", title: "test7" })
];
const myObject = new MyObject(items);
const list = new ListModel([], () => { }, true, null, (text: string) => { myObject.myOnFilter(text); });
const list = new ListModel([], () => { }, true);
list.setOnFilterStringChangedCallback((text: string) => { myObject.myOnFilter(text); });
assert.equal(list.renderedActions.length, 0);

list.setItems(myObject.myItems);
Expand Down Expand Up @@ -142,7 +143,8 @@ QUnit.test("ListModel custom onFilter: item is not found when a search string co
new Action({ id: "test7", title: "test7" })
];
const myObject = new MyObject2(items);
const list = new ListModel([], () => { }, true, null, (text: string) => { myObject.myOnFilter(text); });
const list = new ListModel([], () => { }, true);
list.setOnFilterStringChangedCallback((text: string) => { myObject.myOnFilter(text); });
assert.equal(list.renderedActions.length, 0, "#1");
assert.equal(list.isEmpty, true, "#2");

Expand Down
83 changes: 83 additions & 0 deletions tests/questionDropdownTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Serializer } from "../src/jsonobject";
import { PopupBaseViewModel } from "../src/popup-view-model";
import { PopupDropdownViewModel } from "../src/popup-dropdown-view-model";
import { PopupModalViewModel } from "../src/popup-modal-view-model";
import { QuestionMatrixDynamicModel } from "../src/question_matrixdynamic";

export default QUnit.module("Dropdown question");

Expand Down Expand Up @@ -1919,4 +1920,86 @@ QUnit.test("Test dropdown string localization", function (assert) {

popupViewModel = new PopupModalViewModel(q1.dropdownListModel.popupModel);
assert.equal((popupViewModel as PopupModalViewModel).applyButtonText, "Anwenden", "applyButtonText");
});

QUnit.test("Dropdown choicesLazyLoadEnabled into matrixdynamic", function (assert) {
const done1 = assert.async();
const done2 = assert.async();
const done3 = assert.async();
const survey = new SurveyModel({
"pages": [
{
"name": "page1",
"elements": [
{
"type": "matrixdynamic",
"name": "question1",
"columns": [
{
"cellType": "dropdown",
"name": "country",
"choicesLazyLoadEnabled": true,
"showOtherItem": true
},
{ "name": "country" },
{ "name": "Column3" }
],
"choices": [1, 2, 3, 4, 5]
}
]
}
]
});
survey.onChoicesLazyLoad.add(callback);

const matrix = <QuestionMatrixDynamicModel>survey.getAllQuestions()[0];
const question = <QuestionDropdownModel>matrix.visibleRows[0].cells[0].question;
const itemsSettings = question.dropdownListModel["itemsSettings"];
const listModel: ListModel = question.dropdownListModel.popupModel.contentComponentData.model as ListModel;

assert.equal(question.choicesLazyLoadEnabled, true);
assert.equal(question.choices.length, 5);
assert.equal(itemsSettings.skip, 0);
assert.equal(itemsSettings.take, 25);
assert.equal(itemsSettings.totalCount, 0);
assert.equal(itemsSettings.items.length, 0);

question.dropdownListModel.popupModel.isVisible = true;
setTimeout(() => {
assert.equal(question.choices.length, 25);
assert.equal(question.choices[0].value, 1);
assert.equal(question.choices[24].value, 25);
assert.equal(itemsSettings.skip, 25);
assert.equal(itemsSettings.take, 25);
assert.equal(itemsSettings.totalCount, 55);
assert.equal(itemsSettings.items.length, 25);

listModel.filterString = "2";
setTimeout(() => {
assert.equal(question.choices.length, 25);
assert.equal(question.choices[0].value, 2);
assert.equal(question.choices[24].value, 123);
assert.equal(itemsSettings.skip, 25);
assert.equal(itemsSettings.take, 25);
assert.equal(itemsSettings.totalCount, 55);
assert.equal(itemsSettings.items.length, 25);

listModel.filterString = "22";
setTimeout(() => {
assert.equal(question.choices.length, 25);
assert.equal(question.choices[0].value, 22);
assert.equal(question.choices[24].value, 1223);
assert.equal(itemsSettings.skip, 25);
assert.equal(itemsSettings.take, 25);
assert.equal(itemsSettings.totalCount, 55);
assert.equal(itemsSettings.items.length, 25);

done3();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);

done2();
}, onChoicesLazyLoadCallbackTimeOut + callbackTimeOutDelta);

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

0 comments on commit 7a88d2a

Please sign in to comment.