Fixed #2916 - Add autoFilterFocus property to Dropdown and MultiSelect
parent
bc17ff6022
commit
12190e45fd
|
@ -197,6 +197,12 @@ const DropdownProps = [
|
||||||
default: "true",
|
default: "true",
|
||||||
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
|
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "autoFilterFocus",
|
||||||
|
type: "boolean",
|
||||||
|
default: "false",
|
||||||
|
description: "Whether to focus on the filter element when the overlay panel is shown."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "selectOnFocus",
|
name: "selectOnFocus",
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
|
|
|
@ -209,6 +209,12 @@ const MultiSelectProps = [
|
||||||
default: "true",
|
default: "true",
|
||||||
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
|
description: "Whether to focus on the first visible or selected element when the overlay panel is shown."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "autoFilterFocus",
|
||||||
|
type: "boolean",
|
||||||
|
default: "false",
|
||||||
|
description: "Whether to focus on the filter element when the overlay panel is shown."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "filterMessage",
|
name: "filterMessage",
|
||||||
type: "string",
|
type: "string",
|
||||||
|
|
|
@ -182,6 +182,11 @@ export interface DropdownProps {
|
||||||
* Default value is true.
|
* Default value is true.
|
||||||
*/
|
*/
|
||||||
autoOptionFocus?: boolean | undefined;
|
autoOptionFocus?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Whether to focus on the filter element when the overlay panel is shown.
|
||||||
|
* Default value is false.
|
||||||
|
*/
|
||||||
|
autoFilterFocus?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* When enabled, the focused option is selected.
|
* When enabled, the focused option is selected.
|
||||||
* Default value is false.
|
* Default value is false.
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<slot name="header" :value="modelValue" :options="visibleOptions"></slot>
|
<slot name="header" :value="modelValue" :options="visibleOptions"></slot>
|
||||||
<div v-if="filter" class="p-dropdown-header">
|
<div v-if="filter" class="p-dropdown-header">
|
||||||
<div class="p-dropdown-filter-container">
|
<div class="p-dropdown-filter-container">
|
||||||
<input type="text" ref="filterInput" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-dropdown-filter p-inputtext p-component" :placeholder="filterPlaceholder"
|
<input ref="filterInput" type="text" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-dropdown-filter p-inputtext p-component" :placeholder="filterPlaceholder"
|
||||||
role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
|
role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
|
||||||
@keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
|
@keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
|
||||||
<span class="p-dropdown-filter-icon pi pi-search"></span>
|
<span class="p-dropdown-filter-icon pi pi-search"></span>
|
||||||
|
@ -144,6 +144,10 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
autoFilterFocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
selectOnFocus: {
|
selectOnFocus: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
@ -267,7 +271,7 @@ export default {
|
||||||
this.overlayVisible = true;
|
this.overlayVisible = true;
|
||||||
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
|
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
|
||||||
|
|
||||||
isFocus && this.$refs.focusInput.focus();
|
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||||
},
|
},
|
||||||
hide(isFocus) {
|
hide(isFocus) {
|
||||||
const _hide = () => {
|
const _hide = () => {
|
||||||
|
@ -277,7 +281,7 @@ export default {
|
||||||
this.searchValue = '';
|
this.searchValue = '';
|
||||||
|
|
||||||
this.resetFilterOnHide && (this.filterValue = null);
|
this.resetFilterOnHide && (this.filterValue = null);
|
||||||
isFocus && this.$refs.focusInput && this.$refs.focusInput.focus();
|
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => { _hide() }, 0); // For ScreenReaders
|
setTimeout(() => { _hide() }, 0); // For ScreenReaders
|
||||||
|
@ -390,14 +394,14 @@ export default {
|
||||||
|
|
||||||
if (relatedTarget === this.$refs.focusInput) {
|
if (relatedTarget === this.$refs.focusInput) {
|
||||||
const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
|
const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
|
||||||
firstFocusableEl && firstFocusableEl.focus();
|
DomHandler.focus(firstFocusableEl);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.$refs.focusInput.focus();
|
DomHandler.focus(this.$refs.focusInput);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLastHiddenFocus() {
|
onLastHiddenFocus() {
|
||||||
this.$refs.firstHiddenFocusableElementOnOverlay.focus();
|
DomHandler.focus(this.$refs.firstHiddenFocusableElementOnOverlay);
|
||||||
},
|
},
|
||||||
onOptionSelect(event, option, isHide = true) {
|
onOptionSelect(event, option, isHide = true) {
|
||||||
const value = this.getOptionValue(option);
|
const value = this.getOptionValue(option);
|
||||||
|
@ -571,7 +575,7 @@ export default {
|
||||||
onTabKey(event, pressedInInputText = false) {
|
onTabKey(event, pressedInInputText = false) {
|
||||||
if (!pressedInInputText) {
|
if (!pressedInInputText) {
|
||||||
if (this.overlayVisible && this.hasFocusableElements()) {
|
if (this.overlayVisible && this.hasFocusableElements()) {
|
||||||
this.$refs.firstHiddenFocusableElementOnOverlay.focus();
|
DomHandler.focus(this.$refs.firstHiddenFocusableElementOnOverlay);
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -593,6 +597,8 @@ export default {
|
||||||
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
||||||
this.alignOverlay();
|
this.alignOverlay();
|
||||||
this.scrollInView();
|
this.scrollInView();
|
||||||
|
|
||||||
|
this.autoFilterFocus && DomHandler.focus(this.$refs.filterInput);
|
||||||
},
|
},
|
||||||
onOverlayAfterEnter() {
|
onOverlayAfterEnter() {
|
||||||
this.bindOutsideClickListener();
|
this.bindOutsideClickListener();
|
||||||
|
|
|
@ -202,6 +202,11 @@ export interface MultiSelectProps {
|
||||||
* Default value is true.
|
* Default value is true.
|
||||||
*/
|
*/
|
||||||
autoOptionFocus?: boolean | undefined;
|
autoOptionFocus?: boolean | undefined;
|
||||||
|
/**
|
||||||
|
* Whether to focus on the filter element when the overlay panel is shown.
|
||||||
|
* Default value is false.
|
||||||
|
*/
|
||||||
|
autoFilterFocus?: boolean | undefined;
|
||||||
/**
|
/**
|
||||||
* Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration.
|
* Text to be displayed in hidden accessible field when filtering returns any results. Defaults to value from PrimeVue locale configuration.
|
||||||
* Default value is '{0} results are available'.
|
* Default value is '{0} results are available'.
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="filter" class="p-multiselect-filter-container">
|
<div v-if="filter" class="p-multiselect-filter-container">
|
||||||
<input type="text" ref="filterInput" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-multiselect-filter p-inputtext p-component" :placeholder="filterPlaceholder"
|
<input ref="filterInput" type="text" :value="filterValue" @vnode-updated="onFilterUpdated" class="p-multiselect-filter p-inputtext p-component" :placeholder="filterPlaceholder"
|
||||||
role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
|
role="searchbox" autocomplete="off" :aria-owns="id + '_list'" :aria-activedescendant="focusedOptionId"
|
||||||
@keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
|
@keydown="onFilterKeyDown" @blur="onFilterBlur" @input="onFilterChange" v-bind="filterInputProps"/>
|
||||||
<span class="p-multiselect-filter-icon pi pi-search"></span>
|
<span class="p-multiselect-filter-icon pi pi-search"></span>
|
||||||
|
@ -197,6 +197,10 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
autoFilterFocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
filterMessage: {
|
filterMessage: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null
|
default: null
|
||||||
|
@ -312,7 +316,7 @@ export default {
|
||||||
this.overlayVisible = true;
|
this.overlayVisible = true;
|
||||||
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
|
this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : (this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1);
|
||||||
|
|
||||||
isFocus && this.$refs.focusInput.focus();
|
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||||
},
|
},
|
||||||
hide(isFocus) {
|
hide(isFocus) {
|
||||||
this.$emit('before-hide');
|
this.$emit('before-hide');
|
||||||
|
@ -321,7 +325,7 @@ export default {
|
||||||
this.searchValue = '';
|
this.searchValue = '';
|
||||||
|
|
||||||
this.resetFilterOnHide && (this.filterValue = null);
|
this.resetFilterOnHide && (this.filterValue = null);
|
||||||
isFocus && this.$refs.focusInput.focus();
|
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||||
},
|
},
|
||||||
onFocus(event) {
|
onFocus(event) {
|
||||||
this.focused = true;
|
this.focused = true;
|
||||||
|
@ -413,14 +417,14 @@ export default {
|
||||||
|
|
||||||
if (relatedTarget === this.$refs.focusInput) {
|
if (relatedTarget === this.$refs.focusInput) {
|
||||||
const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
|
const firstFocusableEl = DomHandler.getFirstFocusableElement(this.overlay, ':not(.p-hidden-focusable)');
|
||||||
firstFocusableEl && firstFocusableEl.focus();
|
DomHandler.focus(firstFocusableEl);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.$refs.focusInput.focus();
|
DomHandler.focus(this.$refs.focusInput);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLastHiddenFocus() {
|
onLastHiddenFocus() {
|
||||||
this.$refs.firstHiddenFocusableElementOnOverlay.focus();
|
DomHandler.focus(this.$refs.firstHiddenFocusableElementOnOverlay);
|
||||||
},
|
},
|
||||||
onCloseClick() {
|
onCloseClick() {
|
||||||
this.hide(true);
|
this.hide(true);
|
||||||
|
@ -445,7 +449,7 @@ export default {
|
||||||
value = [...(this.modelValue || []), this.getOptionValue(option)];
|
value = [...(this.modelValue || []), this.getOptionValue(option)];
|
||||||
|
|
||||||
this.updateModel(event, value);
|
this.updateModel(event, value);
|
||||||
isFocus && this.$refs.focusInput.focus();
|
isFocus && DomHandler.focus(this.$refs.focusInput);
|
||||||
index !== -1 && (this.focusedOptionIndex = index);
|
index !== -1 && (this.focusedOptionIndex = index);
|
||||||
},
|
},
|
||||||
onOptionMouseMove(event, index) {
|
onOptionMouseMove(event, index) {
|
||||||
|
@ -646,7 +650,7 @@ export default {
|
||||||
onTabKey(event, pressedInInputText = false) {
|
onTabKey(event, pressedInInputText = false) {
|
||||||
if (!pressedInInputText) {
|
if (!pressedInInputText) {
|
||||||
if (this.overlayVisible && this.hasFocusableElements()) {
|
if (this.overlayVisible && this.hasFocusableElements()) {
|
||||||
this.$refs.firstHiddenFocusableElementOnOverlay.focus();
|
DomHandler.focus(this.$refs.firstHiddenFocusableElementOnOverlay);
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
|
@ -666,6 +670,8 @@ export default {
|
||||||
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
|
||||||
this.alignOverlay();
|
this.alignOverlay();
|
||||||
this.scrollInView();
|
this.scrollInView();
|
||||||
|
|
||||||
|
this.autoFilterFocus && DomHandler.focus(this.$refs.filterInput);
|
||||||
},
|
},
|
||||||
onOverlayAfterEnter() {
|
onOverlayAfterEnter() {
|
||||||
this.bindOutsideClickListener();
|
this.bindOutsideClickListener();
|
||||||
|
|
|
@ -330,6 +330,12 @@ export default {
|
||||||
<td>true</td>
|
<td>true</td>
|
||||||
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
|
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>autoFilterFocus</td>
|
||||||
|
<td>boolean</td>
|
||||||
|
<td>false</td>
|
||||||
|
<td>Whether to focus on the filter element when the overlay panel is shown.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>selectOnFocus</td>
|
<td>selectOnFocus</td>
|
||||||
<td>boolean</td>
|
<td>boolean</td>
|
||||||
|
|
|
@ -351,6 +351,12 @@ export default {
|
||||||
<td>true</td>
|
<td>true</td>
|
||||||
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
|
<td>Whether to focus on the first visible or selected element when the overlay panel is shown.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>autoFilterFocus</td>
|
||||||
|
<td>boolean</td>
|
||||||
|
<td>false</td>
|
||||||
|
<td>Whether to focus on the filter element when the overlay panel is shown.</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>filterMessage</td>
|
<td>filterMessage</td>
|
||||||
<td>string</td>
|
<td>string</td>
|
||||||
|
|
Loading…
Reference in New Issue