QScrollArea cannot programmatically scroll to bottom when contents change #11861
-
When content in the q-scroll-area changes with v-for loop, it is impossible to scroll down to the bottom to see the last item when the data for the v-loop changes(items are added).
Component above can use the area or simple div as example. The div will work but the scroll-area will not. It is important to use the $nextTick to invoke the scrolling behavior, or use flush:post on the watcher. Either will work but without it, both will not work. So even with this fix, the div started to work as expected but the scroll area did not. The bottom item was always below the visible area and the scroll bar was visibly not at the bottom. Quasar version 2.0.0 |
Beta Was this translation helpful? Give feedback.
Replies: 13 comments 2 replies
-
Make a codepen showing the problem |
Beta Was this translation helpful? Give feedback.
-
i don't know how i can create vue component in these services |
Beta Was this translation helpful? Give feedback.
-
I don't think you need components - it looks like all content is quasar components |
Beta Was this translation helpful? Give feedback.
-
It is working just fine: |
Beta Was this translation helpful? Give feedback.
-
You are right, there is something strange with the time needed to render the new message. I got it - the scroll size is calculated using a QResizeObserver, and it has a default debounce of 100ms, so any delay over 100ms should be good. |
Beta Was this translation helpful? Give feedback.
-
So it was a bug after all or configuration issue? Because in that fixed demo i don't see configuration change, hence i take it was a bug? |
Beta Was this translation helpful? Give feedback.
-
In order to be sure that the scroll height of the QScrollArea is calculated after a content update you must allow a delay of more than 100ms (the debounce from QResizeObserver) |
Beta Was this translation helpful? Give feedback.
-
that feels hacky and relies on time which is not concrete and can differ based on the machine that is running the js and therefore can be 100....or not. so that is too unpredictable for me to use. also, why can't it properly calculate the area when i call the method? i would expect that should happen automatically without me having to tell it to do it(which there is no method for anyway). |
Beta Was this translation helpful? Give feedback.
-
As it is now it is always 100+ms (so to be safe you can use setTimeout 110) |
Beta Was this translation helpful? Give feedback.
-
ok, well. it is good to know. it makes it unusable for my use case right now. but at least i will know this for future implementation. |
Beta Was this translation helpful? Give feedback.
-
the ref is not pointing to the right div, unfortunately. i am already doing this with simple div. i just wanted pretty scrollbar but i can do without. |
Beta Was this translation helpful? Give feedback.
-
Should be good now in v2.4.3 |
Beta Was this translation helpful? Give feedback.
-
looks like this is still happening ([email protected]), but interestingly replacing the 1 with 100 as the scroll percentage fixes (work-around?) this example of the problem originally from @falkoschindler on a nicegui discussion <html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" type="text/css" />
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.prod.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="q-app">
<q-scroll-area ref="scrollArea" style="width: 100px; height: 100px; border: 1px solid #ddd">
<div v-for="(label, index) in labels" :key="index">{{ label }}</div>
</q-scroll-area>
<q-btn label="Add" @click="addLabel" />
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/quasar.umd.prod.js"></script>
<script>
const app = Vue.createApp({
setup() {
const labels = Vue.ref([]);
const scrollArea = Vue.ref(null);
const addLabel = () => {
labels.value.push("Hello");
Vue.nextTick(() => scrollArea.value.setScrollPercentage("vertical", 1));
};
return { labels, scrollArea, addLabel };
},
});
app.use(Quasar);
app.mount("#q-app");
</script>
</body>
</html> |
Beta Was this translation helpful? Give feedback.
You are right, there is something strange with the time needed to render the new message.
Updated the codepen here: https://codepen.io/pdanpdan/pen/rNGdqjo?editors=1010
But I need to investigate why it renders so late
I got it - the scroll size is calculated using a QResizeObserver, and it has a default debounce of 100ms, so any delay over 100ms should be good.