Vue multiselect inside of element with scrollbar

See original GitHub issue

Hi, firstly thank you for a great plugin, it’s really great.

I found one issue with using vue vue-multiselect inside of elements with overflow:auto. After to expand, vue multiselect is still inside of the element with overflow auto, which is not how the standard <select> works.

Fiddle: https://jsfiddle.net/jqofkzxc/3078/

Expected behaviour: After to expand the vue-multiselect (.multiselect__content-wrapper) shouldn’t cause the .modal-body to expand.

Possible fix: This could be achieved by setting it outside of element with overflow (.modal-body in that case), and using position absolute + dynamically counted left/top css.

Why? It would make it much easier to use it in replacement to standard <select> without any hacks.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:9 (1 by maintainers)

github_iconTop GitHub Comments

11reactions
me-singhcommented, Mar 25, 2019

Is there any way we can overcome this issue. I want dropdown to appear above overflow (it is blocked by overflow).

4reactions
Kocalcommented, Aug 6, 2020

I’ve used @sigma207 directive, but unfortunately I’ve got two issues with it:

  • when scrolling, the multiselect does not move and that’s weird
  • the parent element lose its height since the multiselect is in position: fixed, so next elements are moved up and this is not wanted

I’ve patched it to use position: absolute instead of fixed, and used an invisible clone to preserve the parent height:

export default {
  install(Vue) {
    Vue.directive('select-overflow', {
      inserted: (el, _binding, vnode) => {
        let originalWidth
        let originalPosition
        let originalZIndex
        let selectIsOpen = false
  
        // will be used as a placeholder, in order to fix parent height issue (due to position relative)
        const clone = el.cloneNode(true);
        clone.style.visibility = 'hidden';

        vnode.child.$watch('isOpen', isOpen => {
          selectIsOpen = isOpen
          if (isOpen) {
            const { offsetWidth } = el
            originalWidth = el.style.width
            originalPosition = el.style.position
            originalZIndex = el.style.zIndex
            el.style.width = `${offsetWidth}px`
            el.style.position = 'absolute'
            el.style.zIndex = 2
            el.parentNode.insertBefore(clone, el.nextSibling); // insert after el
          } else {
            el.style.position = originalPosition
            el.style.width = originalWidth
            el.style.zIndex = originalZIndex
            clone.parentNode.removeChild(clone);
          }
        })

        window.addEventListener('wheel', event => {
          if (selectIsOpen) {
            // disabled outside scroll when select is open
            event.stopPropagation()
          }
        }, true)
      },
    })
  }
}

EDIT: I’ve encountered some issues with the vue-multiselect’s position in a scrollable element, which was not displayed properly. I’m now setting position: relative to the parent element and it’s now working well:

// See https://github.com/shentao/vue-multiselect/issues/723#issuecomment-596988587
// and https://gist.github.com/sigma207/b9300fe12a996c07b2389ee03c1464ed

export const directiveOverflow = {
  inserted: (el, _binding, vnode) => {
    let originalParentPosition;
    let originalWidth;
    let originalPosition;
    let originalZIndex;
    let selectIsOpen = false;

    // will be used as a placeholder, in order to fix parent height issue (due to position relative)
    const clone = el.cloneNode(true);
    clone.style.visibility = 'hidden';

    vnode.child.$watch('isOpen', (isOpen) => {
      selectIsOpen = isOpen;

      if (isOpen) {
        const { offsetWidth } = el;
        originalParentPosition = el.parentElement.style.position;
        originalWidth = el.style.width;
        originalPosition = el.style.position;
        originalZIndex = el.style.zIndex;
        el.parentElement.style.position = 'relative';
        el.style.width = `${offsetWidth}px`;
        el.style.position = 'absolute';
        el.style.zIndex = 9999;
        el.parentNode.insertBefore(clone, el.nextSibling); // insert after el
      } else {
        el.parentElement.style.position = originalParentPosition;
        el.style.position = originalPosition;
        el.style.width = originalWidth;
        el.style.zIndex = originalZIndex;
        clone.parentNode.removeChild(clone);
      }
    });

    window.addEventListener(
      'wheel',
      (event) => {
        if (selectIsOpen) {
          // disabled outside scroll when select is open
          event.stopPropagation();
        }
      },
      true
    );
  },
};
Read more comments on GitHub >

github_iconTop Results From Across the Web

vue-multiselect dropdown list without horizontal scrollbar
One simple solution would be to remove fit-content from .multiselect__element : .multiselect__content-wrapper /*, .multiselect__element ...
Read more >
Vue-Multiselect | Vue Select Library
Probably the most complete selecting solution for Vue.js, without jQuery.
Read more >
Infinite Scroll - Vue Select
Vue Select doesn't ship with first party support for infinite scroll, but it's possible to implement by hooking into the open , close...
Read more >
Vue MultiSelect Component - PrimeFaces
MultiSelect is used to select multiple items from a collection.
Read more >
Vue MultiSelect Component | Kendo UI for Vue - Telerik
Kendo UI for Vue MultiSelect can contain thousands of options in its popup list. With the Virtualization option enabled, the scrolling of many...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found