Vue-multiselect: Append dropdown to body

Created on 27 Dec 2017  路  10Comments  路  Source: shentao/vue-multiselect

Is it somehow possible to append dropdown list to body? I found nothing in docs.
I have overflow: auto container and would like to see .multiselect__content-wrapper over any other element
multiselect

question

Most helpful comment

This is now on the current 3.0 release todo list, once the a11y issues have been solved. Shouldn鈥檛 be long!

All 10 comments

No plans for it right now, though I imagine it might be possible after the 3.0 release and something like vue-portal.

+1

@Hauptsatana @shentao
I have a workaround. Wrap the multiselect element. add ref=multiselect, and use an event handler @open that will invoke this function:

updateDropdownSize(){
    const ms = this.$refs.multiselect;
    ms.$refs.list.style.width = `${this.$el.clientWidth}px`;
    ms.$refs.list.style.position = 'fixed';
}

PS: You can also use on resize event to watch window resize, and invoke this function.

@talberkoSB thank you for this! I also added a scroll handler to move with the dropdown input

@csmoakpax8 Could you please share the scroll handling?

+1 You can also utilize a library like popper.js

@pdcmoreira Sorry for the delay. I have notifications turned off.

mounted() {
  window.addEventListener('scroll', this.repositionDropDown);
},
destroyed() {
  window.removeEventListener('scroll', this.repositionDropDown);
},
repositionDropDown() {
  const { top, height } = this.$el.getBoundingClientRect();
  const ref = this.$refs[`multiselect-${this.id}`];
  ref.$refs.list.style.width = `${this.$el.clientWidth}px`;
  ref.$refs.list.style.position = 'fixed';
  ref.$refs.list.style.bottom = 'auto';
  ref.$refs.list.style.top = `${top + height}px`;
},

I also have @open event call the repositionDropDown method.

@csmoakpax8 Thanks for sharing. I went with kind of a similar approach in the meantime.

I came to a version in which I extend original multiselect with reposition property

Vue.component('multiselect', VueMultiselect)

overrided multiselect VueMultiselect.vue:

<template>
    <vue-multiselect-original
        :ref="$attrs.id"
        v-bind="$attrs"
        v-on="listeners"
        class="position-relative"/>
</template>

<script>
    import Multiselect from 'vue-multiselect'

    export default {
        inheritAttrs: false,
        props: {
            reposition: {
                type: Boolean,
                default: false
            }
        },
        components: {
            'vue-multiselect-original': Multiselect
        },
        computed: {
            listeners() {
                return {
                    ...this.$listeners,
                    open: () => this.onOpen()
                }
            }
        },
        methods: {
            onOpen() {
                if (this.reposition) {
                    if (!this.$attrs.id) {
                        console.error('No multiselect id')
                        return
                    }
                    const {top, height, width, left} = this.$el.getBoundingClientRect()
                    const ref = this.$refs[this.$attrs.id]
                    if (ref) {
                        ref.$refs.list.style.width = `${width}px`
                        ref.$refs.list.style.position = 'fixed'
                        ref.$refs.list.style.bottom = 'auto'
                        ref.$refs.list.style.top = `${top + height}px`
                        ref.$refs.list.style.left = `${left}px`
                    }
                }
            }
        }
    }
</script>

This is now on the current 3.0 release todo list, once the a11y issues have been solved. Shouldn鈥檛 be long!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

wujekbogdan picture wujekbogdan  路  4Comments

volkanciloglu picture volkanciloglu  路  3Comments

dmitov picture dmitov  路  4Comments

stefanheimann picture stefanheimann  路  4Comments

shsmad picture shsmad  路  3Comments