useOnScroll throwing errors
ux-engineer opened this issue · 17 comments
- 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
Can you provide your template code?
Are you assigning tableElementRef
to a HTML element?
@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?
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
@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?
If you provide code somewhere where I can have a look, I can help you better.
@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>
Logging of titleRef.value
shows that the element is found.
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.
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>
@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?
How would this be done in practice?
scrollTo({
top: titleRef.value.offsetTop, // passing the title offset to top
behavior: 'smooth'
});
@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?
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,
};
},
@pikax how to define scroll container if titleRef is given as the param for useOnScroll() instead of scroll container?
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.
@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?
@pikax can scrollIntoView
method do a smooth scrolling instead of jumping immediately to the position, or is it working wrong with my setup?