Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useOnScroll throwing errors #684

Open
ux-engineer opened this issue Dec 8, 2020 · 17 comments
Open

useOnScroll throwing errors #684

ux-engineer opened this issue Dec 8, 2020 · 17 comments

Comments

@ux-engineer
Copy link

  • vue-composable 1.0.0-beta.12
  • vue 2.6.12
  • @vue/composition-api 1.0.0-beta.21
setup: () => {
    const tableElementRef: Ref<HTMLElement | null> = ref(null);

    const { scrollTop, scrollTopTo } = useOnScroll(tableElementRef);
    
    const onClick = async function onClick () {
      // Scroll To Table
      console.debug('tableElementRef', tableElementRef, tableElementRef.value);
      scrollTopTo(scrollTop.value);
      // Fetch via store
      await store.doAction();
    };

    return { tableElementRef, onClick };
}
[Vue warn]: Error in event handler for "hook:beforeUpdate": "TypeError: e.addEventListener is not a function"

TypeError: e.addEventListener is not a function
    addEventListener vue-composable.esm-bundler.js:179
    removeWatch vue-composable.esm-bundler.js:184
    node_modules vue-composition-api.esm.js:1039
    node_modules vue-composition-api.esm.js:982
    node_modules vue-composition-api.esm.js:893
    node_modules vue-composition-api.esm.js:849
    VueJS 7
@pikax
Copy link
Owner

pikax commented Dec 8, 2020

Can you provide your template code?

Are you assigning tableElementRef to a HTML element?

@ux-engineer
Copy link
Author

@pikax ah, ok, I was applying the template ref into a library component. Adding it to a native element cleared the errors.

However, it's not working yet. No scrolling happens. The documentation is quite thin on how to actually use it.

I'm trying to programmatically scroll the viewport up to a component, and hopefully doing a smooth scroll?

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

However, it's not working yet. No scrolling happens. The documentation is quite thin on how to actually use it.

I need to do some work on the documentation.

The way it work is:
You pass a ref with template ref, internally the composable will basically do

<template>
  <div ref="tableElementRef">
   <!-- ... -->
  </div>
</template>
<script>

export default {
 setup(){
  const tableElementRef: Ref<HTMLElement | null> = ref(null);
    
    const onClick = async function onClick () {
      tableElementRef.value.scrollTo({ top: tableElementRef.value.scrollTop } );
    };

    return { tableElementRef, onClick };
 }
}
</script>

useOnScroll is intended to be a wrapper for the HTMLElement.

I'm trying to programmatically scroll the viewport up to a component, and hopefully doing a smooth scroll?

Currently calling scrollTopTo and scrollLeftTo do not use smooth scroll, that needs to be added, but you can always call scrollTo and pass the smooth behaviour.

I was applying the template ref into a library component

I haven't tried with library component, I think in v2 should be straight forward but in v3 with multiple root elements might be a bit tricky

@ux-engineer
Copy link
Author

@pikax sorry but I still could not figure out how to use this - could you post a full setup code example on how to scroll top to a specific element?

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

If you provide code somewhere where I can have a look, I can help you better.

@ux-engineer
Copy link
Author

ux-engineer commented Dec 9, 2020

@pikax here's basically my stripped-down version. scrollTop.value is giving 0 and scrollTo method is not doing anything?

<script lang="ts">
import { defineComponent, ref, Ref } from '@vue/composition-api';
import { useOnScroll } from 'vue-composable';

export default defineComponent({
  setup: () => {
    const titleRef: Ref<HTMLElement | null> = ref(null);

    const { scrollTo, scrollTop } = useOnScroll(titleRef);

    const scrollToElementTop = function scrollToElementTop() {
      console.debug('scrollToElementTop', titleRef.value);
      if (titleRef.value) {
        console.debug('scrollToElementTop - scrolling...', scrollTop.value);
        // scrollTop.value is giving 0 and scrollTo method is not doing anything
        scrollTo({
          top: scrollTop.value,
        });
      }
    };

    return {
      titleRef,
      scrollToElementTop,
    };
  },
});
</script>

<template>
    <div style="padding-top: 300px">
        <h2 ref="titleRef">Title</h2>
        <div style="height: 500px;"></div>
        
        <b-button @click="scrollToElementTop()">Scroll</b-button>
    </div>
</template>

@ux-engineer
Copy link
Author

Logging of titleRef.value shows that the element is found.

@ux-engineer
Copy link
Author

Using scrollTopTo(150); quirks up my layout. It seems plausible that as I'm using simplebar-vue scrollbar library and these contents are within such a scrollable container, that it somehow doesn't along with your composable.

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

Seems you're using it incorrectly, definitely something the docs are not very clear.

The element passed to the useOnScroll needs to be a scrollable element, that element is the one that shows the scrollbar.

At the least in your example, the element who scrolls is the window document, in your case you can change the code to:

<script lang="ts">
import { defineComponent, ref, Ref } from '@vue/composition-api';
import { useOnScroll } from 'vue-composable';

export default defineComponent({
  setup: () => {
    const titleRef: Ref<HTMLElement | null> = ref(null);

    const { scrollTo, scrollTop } = useOnScroll(); // use the document scrollable

    const scrollToElementTop = function scrollToElementTop() {
      console.debug('scrollToElementTop', titleRef.value);
      if (titleRef.value) {
        console.debug('scrollToElementTop - scrolling...', scrollTop.value);
        // scrollTop.value is giving 0 and scrollTo method is not doing anything
        scrollTo({
          top: titleRef.value.offsetTop, // passing the title offset to top
        });
      }
    };

    return {
      titleRef,
      scrollToElementTop,
    };
  },
});
</script>

<template>
  <div style="padding-top: 300px">
    <h2 ref="titleRef">Title</h2>
    <div style="height: 500px;"></div>

    <button @click="scrollToElementTop()">Scroll</button>
  </div>
</template>

@ux-engineer
Copy link
Author

@pikax got it working using vue-scrollTo library. Needed to use .simplebar-content-wrapper as the container, so should be able to get it work with your composable using that container.

you can always call scrollTo and pass the smooth behaviour.

How would this be done in practice?

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

How would this be done in practice?

   scrollTo({
          top: titleRef.value.offsetTop, // passing the title offset to top
          behavior: 'smooth'
        });

@ux-engineer
Copy link
Author

@pikax thanks, smooth scrolling works now.

However I'm still having problem scrolling to the ref'fed element, as offsetTop is giving me value like 20 which is relative to it's own parent and not the scroll container or document? Could I just pass the element href to the method for it to scroll there, and options as the second param?

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

Have you tried to use scrollIntoView?

  setup: () => {
    const titleRef: Ref<HTMLElement | null> = ref(null);

    const { scrollIntoView } = useOnScroll(titleRef); // use the document scrollable

    const scrollToElementTop = function scrollToElementTop() {
      console.debug('scrollToElementTop', titleRef.value);
      if (titleRef.value) {
        scrollIntoView();
      }
    };

    return {
      titleRef,
      scrollToElementTop,
    };
  },

@ux-engineer
Copy link
Author

@pikax how to define scroll container if titleRef is given as the param for useOnScroll() instead of scroll container?

@pikax
Copy link
Owner

pikax commented Dec 9, 2020

if you want to scroll to that component, you probably can you scrollIntoView if you provide an example, I might to be able more, but so far it seems useOnScroll is working as intended.

@ux-engineer
Copy link
Author

@pikax I mean I got this working only by specifying the scroll container by passing it to useOnScroll. If scrollIntoView working by passing the element to which to scroll to useOnScroll, how can I specify the scroll container when doing so?

@ux-engineer
Copy link
Author

@pikax can scrollIntoView method do a smooth scrolling instead of jumping immediately to the position, or is it working wrong with my setup?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants