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

[QScrollArea] setScrollPercentage wrong offset after added element #17472

Closed
KammererTob opened this issue Aug 30, 2024 · 3 comments
Closed

[QScrollArea] setScrollPercentage wrong offset after added element #17472

KammererTob opened this issue Aug 30, 2024 · 3 comments
Labels
area/components bug/2-confirmed We have reproduce the problem and confirmed that this is a bug. flavour/quasar-cli-vite kind/bug 🐞 Qv2 🔝 Quasar v2 issues

Comments

@KammererTob
Copy link

What happened?

Using setScrollPercentage to scroll to the end of the scroll area after adding an element is not working correctly when using nextTick. If you use setTimeout(..., 1) it works as expected.

What did you expect to happen?

It should scroll to the end of the scroll area after adding an element and waiting for the next tick (i.e. after the DOM is updated).

Reproduction URL

https://stackblitz.com/edit/quasarframework-ecbkw4?file=src%2Fpages%2FIndexPage.vue

How to reproduce?

  1. Go to the reproduction
  2. Notice the difference between the two add buttons. One is using setTimeout (with 1ms delay), the other nextTick. The latter is always one element off.

Flavour

Quasar CLI with Vite (@quasar/cli | @quasar/app-vite)

Areas

Components (quasar)

Platforms/Browsers

Firefox

Quasar info output

Operating System - Windows_NT(10.0.19045) - win32/x64
NodeJs - 20.11.1

Global packages
  NPM - 10.2.4
  yarn - 1.22.19
  pnpm - 9.4.0
  bun - Not installed
  @quasar/cli - undefined
  @quasar/icongenie - Not installed
  cordova - Not installed

Important local packages
  quasar - 2.16.9 -- Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
  @quasar/app-vite - 2.0.0-beta.20 -- Quasar Framework App CLI with Vite
  @quasar/extras - 1.16.12 -- Quasar Framework fonts, icons and animations
  eslint-plugin-quasar - Not installed
  vue - 3.4.38 -- The progressive JavaScript framework for building modern web UI.
  vue-router - 4.4.3
  pinia - Not installed
  vuex - Not installed
  vite - 5.4.2 -- Native-ESM powered web dev build tool
  vite-plugin-checker - Not installed
  eslint - 9.9.1 -- An AST-based pattern checker for JavaScript.
  esbuild - 0.23.1 -- An extremely fast JavaScript and CSS bundler and minifier.
  typescript - 5.5.4 -- TypeScript is a language for application scale JavaScript development
  workbox-build - Not installed
  register-service-worker - Not installed
  electron - Not installed
  @electron/packager - Not installed
  electron-builder - Not installed
  @capacitor/core - Not installed
  @capacitor/cli - Not installed
  @capacitor/android - Not installed
  @capacitor/ios - Not installed

Quasar App Extensions
  *None installed*

Relevant log output

No response

Additional context

No response

@github-actions github-actions bot added area/components bug/1-repro-available A reproduction is available and needs to be confirmed. flavour/quasar-cli-vite labels Aug 30, 2024
@yusufkandemir yusufkandemir added bug/2-confirmed We have reproduce the problem and confirmed that this is a bug. and removed bug/1-repro-available A reproduction is available and needs to be confirmed. labels Sep 4, 2024
@yusufkandemir
Copy link
Member

I've recently experienced the same behavior. In my case, the elements were added after calling an Apollo mutation and updating the cache, so wasn't sure where the problem was. But, this issue explains the situation pretty well, thanks.

In your reproduction, setTimeout(..., 1) works better but even that isn't working perfectly. Increasing the timeout makes it work better, e.g. to 200.

@thexeos
Copy link
Contributor

thexeos commented Sep 12, 2024

nextTick is about reactivity and not layout/CSS (which is what the scroll sizes/offsets depend on). What you actually need is to wait for reflow. You can guarantee that reflow had happened if you wait for after the next frame is drawn (aka call requestAnimationFrame twice).

  1. Make reactive change
  2. Wait for reactive change to be flushes to DOM by Vue by waiting for nextTick
  3. Wait for browser to render the frame naturally (you could also trash the layout if you want) by waiting for requestAnimationFrame to trigger
  4. Now you can setup the next requestAnimationFrame callback that would guarantee the layout was recalculated for the previous frame rendering
  5. Finally when callback triggers, browser is ready to accept your changes based on the current state of DOM/layout. ResizeObserver that Quasar uses had definitely triggered and the internal state of Vue/Quasar matches what's in DOM and on the screen - you can call setScrollPosition or setScrollPercentage safely

Arguably Quasar could wait for requestAnimationFrame on your behalf, but Quasar is not aware you've made changes that would result in resize of Scroll Area content, so it's probably best that developers implement this logic in their own code.

function addElement() {
  elements.value.push(++i);
  nextTick(() => {
    // DOM was updated by Vue
    requestAnimationFrame(() => {
      // Browser is about to handle the reflow - the CSS/boundary boxes state is still prior to DOM insertion
      requestAnimationFrame(() => {
        // Browser had definitely recomputed everything and all had notified Quasar of the new scroll content dimensions
        scrollAreaRef.value.setScrollPercentage('horizontal', 1.0, 150);
      });
    });
  });
}

@KammererTob
Copy link
Author

@thexeos Thanks for the explanation and your code example. If there is nothing to "improve" on the Quasar side (maybe apart from mentioning it in the documentation) this can probably be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/components bug/2-confirmed We have reproduce the problem and confirmed that this is a bug. flavour/quasar-cli-vite kind/bug 🐞 Qv2 🔝 Quasar v2 issues
Projects
None yet
Development

No branches or pull requests

3 participants