Fixed #500 - Improvement in behavior of components that have overlay panels in scrollable containers

pull/525/head
mertsincan 2020-09-27 18:26:26 +03:00
parent 3509e3628f
commit 27178a0a51
1 changed files with 29 additions and 2 deletions

View File

@ -1,5 +1,5 @@
<template> <template>
<div :class="containerClass" @click="onClick"> <div ref="container" :id="containerId" :class="containerClass" @click="onClick">
<div class="p-hidden-accessible"> <div class="p-hidden-accessible">
<input ref="focusInput" type="text" role="listbox" :id="inputId" readonly :disabled="disabled" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" :tabindex="tabindex" <input ref="focusInput" type="text" role="listbox" :id="inputId" readonly :disabled="disabled" @focus="onFocus" @blur="onBlur" @keydown="onKeyDown" :tabindex="tabindex"
aria-haspopup="listbox" :aria-expanded="overlayVisible" :aria-labelledby="ariaLabelledBy"/> aria-haspopup="listbox" :aria-expanded="overlayVisible" :aria-labelledby="ariaLabelledBy"/>
@ -55,12 +55,15 @@
</template> </template>
<script> <script>
import ConnectedOverlayScrollHandler from '../utils/ConnectedOverlayScrollHandler';
import UniqueComponentId from '../utils/UniqueComponentId';
import ObjectUtils from '../utils/ObjectUtils'; import ObjectUtils from '../utils/ObjectUtils';
import DomHandler from '../utils/DomHandler'; import DomHandler from '../utils/DomHandler';
import Ripple from '../ripple/Ripple'; import Ripple from '../ripple/Ripple';
export default { export default {
props: { props: {
id: null,
modelValue: null, modelValue: null,
options: Array, options: Array,
optionLabel: null, optionLabel: null,
@ -97,10 +100,13 @@ export default {
}; };
}, },
outsideClickListener: null, outsideClickListener: null,
scrollHandler: null,
overlay: null, overlay: null,
beforeUnmount() { beforeUnmount() {
this.restoreAppend(); this.restoreAppend();
this.unbindOutsideClickListener(); this.unbindOutsideClickListener();
this.unbindScrollListener();
this.scrollHandler = null;
this.overlay = null; this.overlay = null;
}, },
updated() { updated() {
@ -275,10 +281,12 @@ export default {
this.appendContainer(); this.appendContainer();
this.alignOverlay(); this.alignOverlay();
this.bindOutsideClickListener(); this.bindOutsideClickListener();
this.bindScrollListener();
this.$emit('show'); this.$emit('show');
}, },
onOverlayLeave() { onOverlayLeave() {
this.unbindOutsideClickListener(); this.unbindOutsideClickListener();
this.unbindScrollListener();
this.$emit('hide'); this.$emit('hide');
this.overlay = null; this.overlay = null;
}, },
@ -307,6 +315,22 @@ export default {
this.outsideClickListener = null; this.outsideClickListener = null;
} }
}, },
bindScrollListener() {
if (!this.scrollHandler) {
this.scrollHandler = new ConnectedOverlayScrollHandler(this.$refs.container, this.containerId, () => {
if (this.overlayVisible) {
this.hide();
}
});
}
this.scrollHandler.bindScrollListener();
},
unbindScrollListener() {
if (this.scrollHandler) {
this.scrollHandler.unbindScrollListener();
}
},
isOutsideClicked(event) { isOutsideClicked(event) {
return !(this.$el.isSameNode(event.target) || this.$el.contains(event.target) || (this.overlay && this.overlay.contains(event.target))); return !(this.$el.isSameNode(event.target) || this.$el.contains(event.target) || (this.overlay && this.overlay.contains(event.target)));
}, },
@ -356,6 +380,9 @@ export default {
} }
}, },
computed: { computed: {
containerId() {
return this.id || UniqueComponentId();
},
visibleOptions() { visibleOptions() {
if (this.filterValue && this.filterValue.trim().length > 0) if (this.filterValue && this.filterValue.trim().length > 0)
return this.options.filter(option => this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).indexOf(this.filterValue.toLocaleLowerCase(this.filterLocale)) > -1); return this.options.filter(option => this.getOptionLabel(option).toLocaleLowerCase(this.filterLocale).indexOf(this.filterValue.toLocaleLowerCase(this.filterLocale)) > -1);
@ -525,4 +552,4 @@ export default {
.p-fluid .p-multiselect { .p-fluid .p-multiselect {
display: flex; display: flex;
} }
</style> </style>