Skip to content

Commit

Permalink
#7305 Autocomplete doesn't work correctly in dropdown (#7313)
Browse files Browse the repository at this point in the history
* #7305 Autocomplete doesn't work correctly in dropdown
Fixes #7305

* #7305 - fixed angular
  • Loading branch information
novikov82 authored Nov 10, 2023
1 parent 8353d16 commit d102cea
Show file tree
Hide file tree
Showing 33 changed files with 129 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div [class]="model.cssClasses.selectWrapper" (click)="click($event)">
<div *ngIf="!model.isReadOnly" [attr.tabindex]="dropdownModel.inputReadOnly ? null : 0" [class]="model.getControlClass()"
<div *ngIf="!model.isReadOnly" [attr.tabindex]="dropdownModel.noTabIndex ? null : 0" [class]="model.getControlClass()"
[attr.disabled]="model.isInputReadOnly ? true : null" (blur)="blur($event)"
(keydown)="keyhandler($event)" [attr.id]="model.inputId" [attr.aria-required]="model.ariaRequired"
[attr.aria-label]="model.ariaLabel" [attr.aria-invalid]="model.ariaInvalid"
Expand All @@ -23,14 +23,15 @@
[attr.role]="dropdownModel.filterStringEnabled ? model.ariaRole : null"
[attr.id]="model.getInputId()"
[attr.inputmode]="dropdownModel.inputMode"
[attr.tabindex]="dropdownModel.inputReadOnly ? null : -1"
[attr.tabindex]="dropdownModel.noTabIndex ? null : -1"
[attr.disabled]="model.isInputReadOnly ? true : null"
[attr.aria-controls]="dropdownModel.listElementId"
[attr.aria-label]="model.a11y_input_ariaLabel"
[attr.aria-labelledby]="model.a11y_input_ariaLabelledBy"
[attr.aria-expanded]="model.ariaExpanded"
[attr.aria-activedescendant]="dropdownModel.ariaActivedescendant"
[attr.placeholder]="dropdownModel.placeholderRendered" [attr.readonly]="!dropdownModel.searchEnabled ? true : null"
[attr.placeholder]="dropdownModel.placeholderRendered"
[attr.readonly]="dropdownModel.filterReadOnly ? true : null"
(change)="inputChange($event)" (blur)="blur($event)" (focus)="focus($event)"/>
</div>
<div *ngIf="(model.allowClear && model.cssClasses.cleanButtonIconId)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
[class]="question.cssClasses.filterStringInput"
[attr.inputmode]="model.inputMode"
[attr.role]="model.filterStringEnabled ? question.ariaRole : null"
[attr.readonly]="!model.searchEnabled ? true : null"
[attr.readonly]="model.filterReadOnly ? true : null"
[attr.disabled]="question.isInputReadOnly ? true : null"
[attr.size]="!model.inputStringRendered ? 1 : null"
[attr.aria-label]="question.a11y_input_ariaLabel"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div [class]="model.cssClasses.selectWrapper" (click)="click($event)">
<div *ngIf="!model.isReadOnly" [attr.tabindex]="dropdownModel.inputReadOnly ? null : 0" [class]="model.getControlClass()"
<div *ngIf="!model.isReadOnly" [attr.tabindex]="dropdownModel.noTabIndex ? null : 0" [class]="model.getControlClass()"
[attr.disabled]="model.isInputReadOnly ? true : null" (blur)="blur($event)"
(keydown)="keyhandler($event)" [attr.id]="model.inputId" [attr.aria-required]="model.ariaRequired"
[attr.aria-label]="model.ariaLabel" [attr.aria-invalid]="model.ariaInvalid"
Expand Down
6 changes: 3 additions & 3 deletions packages/survey-vue3-ui/src/components/dropdown/Dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
v-if="!question.isReadOnly"
:id="question.inputId"
:disabled="question.isInputReadOnly ? true : null"
:tabindex="model.inputReadOnly ? undefined : 0"
:tabindex="model.noTabIndex ? undefined : 0"
@keydown="keyhandler"
@blur="blur"
:class="question.getControlClass()"
Expand Down Expand Up @@ -56,8 +56,8 @@
:inputmode="model.inputMode"
:role="model.filterStringEnabled ? question.ariaRole : undefined"
:id="question.getInputId()"
:tabindex="model.inputReadOnly ? undefined : -1"
:readonly="!model.searchEnabled ? true : undefined"
:tabindex="model.noTabIndex ? undefined : -1"
:readonly="model.filterReadOnly ? true : undefined"
:aria-expanded="
question.ariaExpanded === null
? undefined
Expand Down
2 changes: 1 addition & 1 deletion packages/survey-vue3-ui/src/components/tagbox/Tagbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div
v-if="!question.isReadOnly"
:id="question.inputId"
:tabindex="model.inputReadOnly ? undefined : 0"
:tabindex="model.noTabIndex ? undefined : 0"
v-bind:disabled="question.isInputReadOnly ? true : null"
@keydown="keyhandler"
@blur="blur"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
:aria-labelledby="question.a11y_input_ariaLabelledBy"
:aria-activedescendant="model.ariaActivedescendant"
:id="question.getInputId()"
:readonly="!model.searchEnabled ? true : undefined"
:readonly="model.filterReadOnly ? true : undefined"
:size="!model.inputStringRendered ? 1 : undefined"
@change="inputChange"
@keydown="inputKeyHandler"
Expand Down
7 changes: 5 additions & 2 deletions src/dropdownListModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class DropdownListModel extends Base {

private _markdownMode = false;
private _popupModel: PopupModel;
focused: boolean;
@property({ defaultValue: false }) focused: boolean;
private get focusFirstInputSelector(): string {
return this.getFocusFirstInputSelector();
}
Expand Down Expand Up @@ -339,9 +339,12 @@ export class DropdownListModel extends Base {
get popupModel(): PopupModel {
return this._popupModel;
}
public get inputReadOnly(): boolean {
public get noTabIndex(): boolean {
return this.question.isInputReadOnly || this.searchEnabled;
}
public get filterReadOnly(): boolean {
return this.question.isInputReadOnly || !this.searchEnabled || !this.focused;
}
public get filterStringEnabled(): boolean {
return !this.question.isInputReadOnly && this.searchEnabled;
}
Expand Down
6 changes: 3 additions & 3 deletions src/knockout/components/dropdown/dropdown.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
attr: {
id: question.inputId,
required: question.isRequired,
tabindex: model.inputReadOnly ? undefined : 0,
tabindex: model.noTabIndex ? undefined : 0,
disabled: question.isInputReadOnly,
role: question.ariaRole,
'aria-required': question.ariaRequired,
Expand Down Expand Up @@ -46,9 +46,9 @@
'aria-label': question.a11y_input_ariaLabel,
'aria-labelledby': question.a11y_input_ariaLabelledBy,
placeholder: model.placeholderRendered,
readonly: !model.searchEnabled,
readonly: model.filterReadOnly || undefined,
role: model.filterStringEnabled ? question.ariaRole : undefined,
tabindex: model.inputReadOnly ? undefined : -1,
tabindex: model.noTabIndex ? undefined : -1,
disabled: question.isInputReadOnly,
id: question.getInputId(),
inputmode: model.inputMode
Expand Down
4 changes: 2 additions & 2 deletions src/knockout/components/tagbox/tagbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
attr: {
id: question.inputId,
required: question.isRequired,
tabindex: model.inputReadOnly ? undefined : 0,
tabindex: model.noTabIndex ? undefined : 0,
disabled: question.isInputReadOnly,
role: question.ariaRole,
'aria-required': question.ariaRequired,
Expand Down Expand Up @@ -48,7 +48,7 @@
'aria-labelledby': question.a11y_input_ariaLabelledBy,
placeholder: model.filterStringPlaceholder,
disabled: question.isInputReadOnly,
readonly: !model.searchEnabled
readonly: model.filterReadOnly
},
event: { keydown: inputKeyHandler, blur: blur, focus: focus }"></input>
</div>
Expand Down
6 changes: 3 additions & 3 deletions src/react/dropdown-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export class SurveyQuestionDropdownBase<T extends Question> extends SurveyQuesti
return (<div
id={this.question.inputId}
className={this.question.getControlClass()}
tabIndex={dropdownListModel.inputReadOnly ? undefined : 0}
tabIndex={dropdownListModel.noTabIndex ? undefined : 0}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
disabled={this.question.isInputReadOnly}
Expand Down Expand Up @@ -124,8 +124,8 @@ export class SurveyQuestionDropdownBase<T extends Question> extends SurveyQuesti
aria-controls={dropdownListModel.listElementId}
aria-activedescendant={dropdownListModel.ariaActivedescendant}
placeholder={dropdownListModel.placeholderRendered}
readOnly={!dropdownListModel.searchEnabled ? true : undefined}
tabIndex={dropdownListModel.inputReadOnly ? undefined : -1}
readOnly={dropdownListModel.filterReadOnly ? true : undefined}
tabIndex={dropdownListModel.noTabIndex ? undefined : -1}
disabled={this.question.isInputReadOnly}
inputMode={dropdownListModel.inputMode}
onChange={(e) => { onInputChange(e); }}
Expand Down
2 changes: 1 addition & 1 deletion src/react/reactquestion_tagbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class SurveyQuestionTagbox extends SurveyQuestionDropdownBase<QuestionTag
<div
id={this.question.inputId}
className={this.question.getControlClass()}
tabIndex={dropdownListModel.inputReadOnly ? undefined : 0}
tabIndex={dropdownListModel.noTabIndex ? undefined : 0}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
disabled={this.question.isInputReadOnly}
Expand Down
2 changes: 1 addition & 1 deletion src/react/tagbox-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class TagboxFilterString extends SurveyElementBase<ITagboxFilterProps, an
ref={(element) => (this.inputElement = element)}
className={this.question.cssClasses.filterStringInput}
disabled={this.question.isInputReadOnly}
readOnly={!this.model.searchEnabled ? true : undefined}
readOnly={this.model.filterReadOnly ? true : undefined}
size={!this.model.inputStringRendered ? 1 : undefined}
role={this.model.filterStringEnabled ? this.question.ariaRole : undefined}
aria-expanded={this.question.ariaExpanded === null ? undefined : this.question.ariaExpanded === "true"}
Expand Down
6 changes: 3 additions & 3 deletions src/vue/components/dropdown/dropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
v-if="!question.isReadOnly"
:id="question.inputId"
v-bind:disabled="question.isInputReadOnly"
:tabindex="model.inputReadOnly ? undefined : 0"
:tabindex="model.noTabIndex ? undefined : 0"
@keydown="keyhandler"
@blur="blur"
:class="question.getControlClass()"
Expand Down Expand Up @@ -47,8 +47,8 @@
:inputmode="model.inputMode"
:role="model.filterStringEnabled ? question.ariaRole : null"
:id="question.getInputId()"
:tabindex="model.inputReadOnly ? undefined : -1"
:readonly="!model.searchEnabled ? true : null"
:tabindex="model.noTabIndex ? undefined : -1"
:readonly="model.filterReadOnly ? true : null"
:aria-expanded="question.ariaExpanded"
:aria-label="question.a11y_input_ariaLabel"
:aria-labelledby="question.a11y_input_ariaLabelledBy"
Expand Down
2 changes: 1 addition & 1 deletion src/vue/components/tagbox/tagbox-filter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
:aria-controls="model.listElementId"
:aria-activedescendant="model.ariaActivedescendant"
:id="question.getInputId()"
:readonly="!model.searchEnabled ? true : null"
:readonly="model.filterReadOnly ? true : null"
:size="!model.inputStringRendered ? 1 : null"
@change="inputChange"
@keydown="inputKeyHandler"
Expand Down
2 changes: 1 addition & 1 deletion src/vue/components/tagbox/tagbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div
v-if="!question.isReadOnly"
:id="question.inputId"
:tabindex="model.inputReadOnly ? undefined : 0"
:tabindex="model.noTabIndex ? undefined : 0"
v-model="question.renderedValue"
v-bind:disabled="question.isInputReadOnly"
@keydown="keyhandler"
Expand Down
10 changes: 10 additions & 0 deletions tests/dropdown_list_model_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -881,3 +881,13 @@ QUnit.test("order & locale change", function (assert) {
assert.equal(list.actions[0].id, "B", "action[0].id, de");
assert.equal(list.actions[1].id, "A", "action[1].id, de");
});
QUnit.test("DropdownListModel filterReadOnly", (assert) => {
const survey = new SurveyModel(jsonDropdown);
const question = <QuestionDropdownModel>survey.getAllQuestions()[0];
const dropdownListModel = question.dropdownListModel;
assert.ok(dropdownListModel.filterReadOnly);
dropdownListModel.onFocus(null);
assert.notOk(dropdownListModel.filterReadOnly);
dropdownListModel.onBlur({ stopPropagation: () => { } });
assert.ok(dropdownListModel.filterReadOnly);
});
27 changes: 27 additions & 0 deletions tests/markup/etalon_dropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,33 @@ registerMarkupTests(
removeIds: true,
snapshot: "dropdown-input-string",
},
{
name: "Test Dropdown question input focused",
json: {
questions: [
{
"type": "dropdown",
"name": "name",
"title": "Question title",
"searchEnabled": true,
"choices": [
"Ford",
"Vauxhall",
"Volkswagen",
],
titleLocation: "hidden",
}
]
},
initSurvey: (survey) => {
survey.focusFirstQuestionAutomatic = false;
survey.getQuestionByName("name")["popupModel"];
survey.getQuestionByName("name")["dropdownListModel"].focused = true;
},
timeout: 300,
removeIds: true,
snapshot: "dropdown-input-focused",
},
{
name: "Test dropdown aria-expanded",
json: {
Expand Down
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-aria-expanded.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="sv_select_wrapper">
<div aria-controls="testid0i_list" aria-expanded="true" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<input aria-controls="testid0i_list" aria-expanded="true" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="Select..." role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="true" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="Select..." readonly="" role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" style="display:none;" tabindex="0">
<svg class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
Expand Down
35 changes: 35 additions & 0 deletions tests/markup/snapshots/dropdown-input-focused.snap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<div>
<div class="sv_select_wrapper">
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" role="combobox">
<div class="sv_q_dropdown__value">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" inputmode="text" placeholder="Select..." role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" style="display:none;">
<svg aria-label="Clear" class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
<use xlink:href="#icon-clear_16x16" class="">
</use>
<title class="">Clear</title>
</svg>
</div>
</div>
<div>
<div class="sv-dropdown-popup sv-popup sv-popup--dropdown sv-single-select-list" style="display:none;" tabindex="-1">
<div class="sv-popup__container">
<div class="sv-popup__shadow">
<div class="sv-popup__body-content">
<div class="sv-popup__scrolling-content">
<div class="sv-popup__content">
<div class="sv-list__container">
<div class="sv-list__empty-container" style="display:none;">
<div aria-label="No data to display" class="sv-list__empty-text">No data to display</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-input-string.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<span style="visibility:hidden;">o</span>
<span>rd</span>
</div>
<input aria-controls="testid0i_list" aria-expanded="true" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" inputmode="text" placeholder="" role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="true" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" inputmode="text" placeholder="" readonly="" role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" style="display:none;" tabindex="0">
<svg class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<span class="sv-string-viewer">item1</span>
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" readonly="" role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" tabindex="0">
<svg class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
Expand Down
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-select-mobile.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="sv_select_wrapper">
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="none" placeholder="Select..." role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="none" placeholder="Select..." readonly="" role="combobox" type="text">
</div>
</div>
<div>
Expand Down
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-select.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<div class="sv_select_wrapper">
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="Select..." role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="Select..." readonly="" role="combobox" type="text">
</div>
</div>
<div>
Expand Down
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-with-markdown.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<span class="sv-string-viewer">Cat: ![A cat](https://surveyjs.io/Content/Images/examples/markdown/cat.svg =14x14)</span>
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" readonly="" role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" tabindex="0">
<svg class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
Expand Down
2 changes: 1 addition & 1 deletion tests/markup/snapshots/dropdown-with-none-value.snap.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<div aria-controls="testid0i_list" aria-expanded="false" aria-invalid="false" aria-label="Question title" aria-required="false" class="sv_q_dropdown_control" id="testid0i" role="combobox">
<div class="sv_q_dropdown__value">
<span class="sv-string-viewer">None</span>
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" role="combobox" type="text">
<input aria-controls="testid0i_list" aria-expanded="false" aria-label="Question title" autocomplete="off" class="sv_q_dropdown__filter-string-input" id="testid0i_0" inputmode="text" placeholder="" readonly="" role="combobox" type="text">
</div>
<div class="sv_q_dropdown_clean-button" tabindex="0">
<svg class="sv_q_dropdown_clean-button-svg sv-svg-icon" role="img">
Expand Down
Loading

0 comments on commit d102cea

Please sign in to comment.