0

I have an element part of a modal, like this:

<template>
    <portal to="portal-level-3">
        <div
            v-if="isOpen"
            class="fixed z-50 px-4 pb-4 inset-0 flex items-center justify-center"
            :class="[isContentHeightGreaterThanHolder ? 'items-baseline' : 'items-center']"
        >
            <div
                class="fixed inset-0 transition-opacity"
                enter-active-class="ease-out duration-300"
                enter-class="opacity-0"
                enter-to-class="scale-100"
                leave-active-class="ease-in duration-200"
                leave-class="opacity-100"
                leave-to-class="opacity-0"
            >
                <div class="absolute inset-0 bg-gray-500 opacity-75"></div>
            </div>

            <div
                v-if="isOpen"
                v-click-outside="closeModal"
                ref="refContent"
                :class="[
                    notFullWidth ? '' : 'w-full',
                    modalWidthClass
                ]"
                class="bg-white rounded-lg overflow-hidden shadow-xl transform transition-all px-4 pt-5 pb-4"
                enter-active-class="ease-out duration-300"
                enter-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                enter-to-class="opacity-100 translate-y-0 sm:scale-100"
                leave-active-class="ease-in duration-200"
                leave-class="opacity-100 translate-y-0 sm:scale-100"
                leave-to-class="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
            >

                <div class="flex mb-4">
                    <div v-if="title" class="flex-1">
                        <h3 class="text-lg leading-6 font-medium text-brand">
                            {{ title }}
                        </h3>
                    </div>

                    <div class="pl-3">
                        <button
                            @click.prevent="closeModal()"
                            type="button"
                            class="text-gray-400 hover:text-gray-500 focus:outline-none focus:text-gray-500 transition ease-in-out duration-150"
                        >
                            <font-awesome-icon class="h-6 w-6" :icon="['fal', 'times']" />
                        </button>
                    </div>
                </div>

                <slot></slot>

            </div>
        </div>
    </portal>

</template>

In the Vue instance, I watch for the modal opening like this:

watch: {
    visible(val) {
        this.isOpen = val
    },
    isOpen(val) {
        if (val) {
            this.$nextTick(() => {
                let holderHeight = this.$el.offsetHeight
                let contentHeight = this.$refs.refContent.offsetHeight
                this.isContentHeightGreaterThanHolder = contentHeight >= (holderHeight - 30)
            })
        }
    }
},

But this results in:

"TypeError: Cannot read property 'offsetHeight' of undefined"

But if I console.log(this.$refs) I get:

{}
refContent: div.bg-white.rounded-lg.overflow-hidden.shadow-xl.transform.transition-all.px-4.pt-5.pb-4.w-full.max-w-xl
@@clickoutsideContext: {id: 5, methodName: "closeModal", documentHandler: ƒ, bindingFn: ƒ}
accessKey: ""
align: ""
ariaAtomic: null
ariaAutoComplete: null
ariaBusy: null
ariaChecked: null
ariaColCount: null
ariaColIndex: null
ariaColSpan: null
ariaCurrent: null
ariaDescription: null
ariaDisabled: null
ariaExpanded: null
....
offsetHeight: 805

Why can I not access this.$refs.refContent.offsetHeight? Thanks!

TheRealPapa
  • 4,393
  • 8
  • 71
  • 155
  • In which cycle do you use this method also if you are trying to resize some elements based on that offsetHeight you might not need javascript, you can solve it with only using css maybe your problem is similar to this example [reddit link of similar problem](https://www.reddit.com/r/vuejs/comments/977ofl/trying_to_get_and_change_my_header_and_footer/e48ktl4/?context=8&depth=9) if this is not your problem provide more code please. – Elvaleryn Oct 07 '20 at 10:29
  • Hi @Elvaleryn, I have updated the question. I am trying toposition the modal based on height of its content. – TheRealPapa Oct 07 '20 at 10:46
  • refContent may be unavailable at the time when v-if is rendered. The logic seems to be faulty, the ref is on the the same element as v-if, this is chicken/egg paradox. – Estus Flask Oct 07 '20 at 10:50
  • 2
    checkout this it is a bug in the library which you use: [github link](https://github.com/LinusBorg/portal-vue/issues/118). There couple workarounds in that thread one of them is to wrap logic in nextick twice. ` this.$nextTick(() => { this.$nextTick(() => { //code }) })` – Elvaleryn Oct 07 '20 at 10:57

0 Answers0