Composition-api: Access value of template ref inside of comosable function

Created on 7 Oct 2020  路  6Comments  路  Source: vuejs/composition-api

I have a composable function looking like this:

import { reactive, ref, onMounted } from '@vue/composition-api';
import Glider from 'glider-js/glider';
import { find, debounce } from 'lodash';
import { PAGE_THUMB_CLASS } from '@/config/page-thumbs';

const pageThumbScroller = (props) => {
  let thumbSlider;

  // template refs
  const pageThumbsSwiper = ref(null);
  const pageThumbsContainer = ref(null);
  const prevButton = ref(null);
  const nextButton = ref(null);

  const thumbsContainerWidth = () => pageThumbsContainer.value.getBoundingClientRect().width;

  const visibleItems = () => {
    if (!pageThumbsSwiper) {
      return {};
    }
    const containerSize = thumbsContainerWidth();
    return containerSize / props.itemWidthPlusPadding;
  };

  const initSlider = () => {
    // eslint-disable-next-line no-new
    thumbSlider = reactive(new Glider(pageThumbsSwiper.value, {
      slidesToShow: visibleItems(),
      slidesToScroll: 'auto',
      itemWidth: props.itemWidthPlusPadding,
      draggable: true,
      dragVelocity: 1,
      duration: 0.3,
      arrows: {
        prev: prevButton.value.$el,
        next: nextButton.value.$el,
      },
    }));
  };

  const updateSlider = () => {
    thumbSlider.setOption({ slidesToShow: visibleItems() });
    thumbSlider.refresh(true);
  };

  const getThumbsBySelector = (identifier) => {
    // ----------------------------------
    // PROBLEM!!! => pageThumbsSwiper.value is always null, but if I use the same in onMounted, it is not
    // console.log(pageThumbsSwiper) => return an Object RefImpl with the correct value, but pageThumbsSwiper.value does not return anything
    // ----------------------------------
    if (!pageThumbsSwiper.value) {
      return [];
    }
    return Array.from(pageThumbsSwiper.value.querySelectorAll(identifier));
  };

  const scrollToActivePage = (activePageId) => {
    const activeThumb = getThumbsBySelector(`[data-id='${activePageId}']`);

    if (
      activeThumb.length === 0
      || find(activeThumb[0].classList, (className) => className === PAGE_THUMB_CLASS.VISIBLE)
    ) {
      return;
    }

    if (find(
      activeThumb[0].classList,
      (className) => className.includes(PAGE_THUMB_CLASS.LEFT),
    )) {
      // if item is on the left side, scroll to first position
      const allThumbs = getThumbsBySelector(PAGE_THUMB_CLASS.GENERAL);
      const indexActive = allThumbs
        .findIndex((thumb) => parseInt(thumb.dataset.id, 10) === activePageId);

      thumbSlider.scrollItem(indexActive);
      return;
    }

    const containerSize = thumbsContainerWidth();
    const offsetActive = activeThumb[0].offsetLeft;
    const scrollOffset = offsetActive - containerSize + props.itemWidthPlusPadding;

    thumbSlider.scrollTo(scrollOffset);
  };

  const onResize = debounce(updateSlider, 50);

  onMounted(() => {
    window.addEventListener('resize', onResize);
    initSlider();
  });

  return {
    pageThumbsSwiper,
    pageThumbsContainer,
    prevButton,
    nextButton,
    initSlider,
    updateSlider,
    scrollToActivePage,
  };
};

export {
  pageThumbScroller,
};

Like written above in the comment, i need the value of the pageThumbsSwiper, but I can't access it, is there a special method how to do that. PageThumbsSwiper is a template ref and i need its value in getThumbsBySelector. The problem is written in the Code from // ---------------------------------- on.

Accessing the same value in the onMounted, i get the correct result. Please help me...

Most helpful comment

lmao same question here. Do you guys want to maybe document this???

e: for anyone in the future, solved this by getting rid of v-if on the element and instead using v-show. Then myRef.value is defined

All 6 comments

You will get access to template ref in onMonunted. This is expected behaviour. https://github.com/vuejs/composition-api#template-refs

Ask questions on Discord or Stackoverflow next time. Thanks.

Ok, as already written, I saw that. But it does not solve my problem... How can I use the value anywhere else? I can't assign the value in onMounted to a variable that I use in the function, how can i access it, or is it just not possible? And why do you close the issue?

https://v3.vuejs.org/guide/composition-api-template-refs.html#template-refs

why do you close the issue?

Ask questions on Discord or Stackoverflow.

Thanks for your self-sacrificing help

Good question, same problem here - any solutions yet?

lmao same question here. Do you guys want to maybe document this???

e: for anyone in the future, solved this by getting rid of v-if on the element and instead using v-show. Then myRef.value is defined

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ggedde picture ggedde  路  4Comments

TooBug picture TooBug  路  6Comments

sapphi-red picture sapphi-red  路  4Comments

zzachattack2 picture zzachattack2  路  3Comments

ycmjason picture ycmjason  路  5Comments