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

fix(virtual-scroll) many fixes #12194

Closed

Conversation

pablomaurer
Copy link

@pablomaurer pablomaurer commented Jun 28, 2017

Ionic Version: 3.x

Short description of what this resolves:

maybe also #10971

Influences / How I worked

I went through the history of virtual-scroll.ts and took an older version where people said it was better. Then I added the changes slowly again to find out where some bugs where introduced.

I also compared stuff with angular's ngForOf implementation because ionic also did this in the start, but with time ionic drifted more and more off.

Changes proposed in this pull request:

  • never update the _differ, create it only if it does not already exists. don't use the setter instead uses the ngOnChanges. why? ngFor is also like this. May solves some init problems. Easier to reason about.
  • removed the check if there are records in _changes(). why? because if we clear the items array with setting it to null, the clearing get's never proceeded.
  • only get records length if there are records. why? because with the above change it's now possible that _records is null.
  • removed the wrapping this._plt.raf(() in renderVirtual(). why? because this caused the flickering while updating the list. caution I'm not sure why or what this._plt.raf(() did, so may review this point a bit deeper.
  • includes PR fix(virtualScroll) remove items if array is null #12134 there is also a bit a description.

How the issues came and what we should care in future.

I think a lot issues came with changes to get virtual-scroll with InfiniteScroll together working, but I think it's more important to get virtual-scroll battle tested before getting it to work with other stuff which may introduces new bugs. PS: I didn't test the changes InfiniteScroll.

Don't care about everything below, you are free to merge..

My WIP Notes - for even further improvements


Semantic issues

Would look better in a separate PR, so this PR, stays clean with just fixes.

rename

  • processRecords() rename to addCells() why? Nobody know's what it's gonna process.
  • addCell() rename tocreateCell() why? it doesn't add anything, it just returns a cell.
  • readElements() rename tocalcCellDimension() keep consistent with calcDimensions. And readElements doesn't give any hint about, that it will change any data.

modified by reference

  • processRecords() modifies _cells by reference and doesn't return anything, looks a bit weird.
  • calcDimension() modifies _data by reference and doesn't return anything, looks a bit weird.

more

  • in renderVirtual() remove resetting topCell/bottomCell, because they get overwritten anyway in the following adjustRendering().
  • before everywriteUpdate() you call readUpdate() or updateDimensions() which is contained in readUpdate(). Just put readUpdate as first line into writeUpdate().
  • before every adjustRendered() you call updateDimensions() so put updateDimensions() in adjustRendered().
  • updateDimensions() would split it into calcCellDimensions() and updateEstimatedDimensions().
  • virtual-util.ts contains a lot var replace with let?
  • readElements() here you update cell.left but in updateDimensions() it will get overwritten anyway.

Overview helps me finding out what is going on when..

init/data changes

  • readUpdate()->calcDimension() updates heigth/width/top/left of data and guesses itmWidth/itmHeigth
  • writeUpdate()->processRecords() records to Cells
  • writeUpdate()->renderVirtual()->updateDimensions() calcCellDimensions
  • writeUpdate()->renderVirtual()->adjustRendered() set topCell/bottomCell in data finds out which cells should be rendered.
  • writeUpdate()->renderVirtual()->populateNodeData() assign cells to nodes.
  • writeUpdate()->renderVirtual()->initReadNodes() update first cell with position of first node and updateDimensions() again?
  • writeUpdate()->renderVirtual()->updateNodeContext() updates positions of the nodes?
  • writeUpdate()->renderVirtual()->_stepChangeDetection() detect changes in nodes?
  • writeUpdate()->renderVirtual()->_stepDOMWrite() set positions of nodes on the dom

scroll

  • _stepNoChanges()->processRecords() records to Cells
  • _stepNoChanges()->updateDimensions() calcCellDimensions
  • _stepNoChanges()->adjustRendered() set topCell/bottomCell in data finds out which cells should be rendered.
  • _stepNoChanges()->populateNodeData() assign cells to nodes.
  • _stepNoChanges()->updateNodeContext() updates positions of the nodes?

what's the difference of stepsNoChanges and writeUpdate?
what's the difference of writeUpdate and _stepDOMWrite

brandyscarney and others added 30 commits June 12, 2017 13:51
When `Tabs` are nested within each other, the highlight can get
misaligned. This prevents that by ensuring the affected
`.tab-highlight` is a direct child of the targeted `Tabs`.
…tabs

* wip

* wip

* progress

* wippy skippy

* getting there

* all tests passing except goBack

* unit tests pass again boi

* goBack tests pass

* great success

* the good stuff
@pablomaurer
Copy link
Author

pablomaurer commented Jun 30, 2017

Ionic-team please decide between if I should go for Case 2 or Case 3

In virtual-util.ts there is calcDimensions() with this line:

const viewportElement = virtualScrollElement.parentElement;
data.viewHeight = viewportElement.offsetHeight;
data.renderHeight = (data.viewHeight * bufferRatio);

So this code, get's the dimensions for virtual-scroll before it will render the new nodes. But that it's before causes issues and getting it after is to late.

This causes the following behavior:

Case 1, parent of virtual-scroll is ion-content

Works because, when the parent of virtual-scroll is the ion-content it will get the offset-height of scroll-content which is ever the full-height. Because like this the viewHeight will ever stay the same.

solution: works anyway.

Case 2, parent of virtual-scroll is div with height not set

Fails because, when you put virtual-scroll in a div with no height-specified. It will ever use the height it had before rendering the new nodes. So if you replace and array with 3 items with an array of 50 items. It will use the renderHeight for 3 items, even you are displaying 50 items. which results in only seeing 3 items while scrolling and seeing a lot of blank space.

solution: just act as we where in case 1. I'm new to angular and I don't saw that you ever used something like getElementsBy... So please advice me what to use instead!

let el = document.getElementsByClassName('scroll-content')[0] as HTMLElement;
data.viewHeight = el.offsetHeight;

Case 3, parent of virtual-scroll is div with fixed-height and overflow:scroll

This would also be somehow cool, since it would make support for multiple virtual-scrolls.
Now this is better than case 2, because thanks to the fixes-height we got the correct renderHeight, but the scrollListeners are listening to the ion-content so it would not update while scrolling.

solution: attach scroll-listener to parent element and say people that virtual-scroll must be in a container with a fixed-heigth and a overflow:scroll.

@HugoHeneault
Copy link

Hey there! I'd like to implement these fixes in my ionic3 project, but I don't know how to do it. @mnewmedia how can I achieve it? Thanks a lot for your work!

@pablomaurer
Copy link
Author

@HugoHeneault There is no easy way I know to implement this fixes in an existing project.

@HugoHeneault
Copy link

HugoHeneault commented Jul 19, 2017

Okay, so we just have to wait I guess :( Thanks for your reply!

@AmitMY
Copy link
Contributor

AmitMY commented Jul 20, 2017

@speedtreammanga Please post this as an issue. This does not belong in the PR thread

@HugoHeneault
Copy link

HugoHeneault commented Jul 22, 2017

If anyone is willing to try this PR easily, you can remplace your ionic-angular by this folder we've built:
ionic-angular.zip

@nilebma
Copy link

nilebma commented Aug 3, 2017

Thanks for compiling this PR in a new version @HugoHeneault. If by any chance you did the same kind of package for [email protected], I'll be very interested :-)

@beckson
Copy link

beckson commented Aug 5, 2017

any news to the virtual-scroll?
I had the same problem, using virtual-scroll like

<ion-content>
  <ion-scroll>
      <ion-list [virtualScroll]="xxx">
      </ion-list>
 </ion-scroll>
 <ion-scroll>
</ion-scroll>
</<ion-content>

@HugoHeneault
Copy link

@nilebma I don't have this. But you could clone the ionic repo, then apply the changes of this PR to the current ionic repo, then build it. :)

@tonypig93
Copy link

Hi, I've download the folder you built and it works fine, solved the annoying flickers, but I got another problem. After ion-infinite-scroll fetches data several times, the list display blank in the viewport until I continue scroll down then I can see items rendered, actually I've came to this problem before your commit, can you take a look at it? Plus, will this PR be included in the next Ionic release?

@masimplo
Copy link
Contributor

masimplo commented Aug 31, 2017

Here is the compiled version for 3.6.0 for whoever needs it.
Whole library: ionic-angular.zip
Only virtual scroll folder: virtual-scroll.zip
Just the patch: virtual-scroll.patch.txt

Please give some attention to virtual scroll, it has been broken for many months now.

@masimplo
Copy link
Contributor

masimplo commented Sep 18, 2017

This might not be the correct path to take to fix the issue. Removing RequestAnimationFrame wrapper made virtualScroll not render correctly in actual devices (probably because they are slower and thus queuing system is needed). Besides, completely disposing of nodes every time the dataset changes was always problematic and even if you can fake it, there will always be a performance impact. After extensive tests with this pull request's code and meticulous debugging of the original code I have come up with a pull request that addresses the above issues by changing the core handling of what happens when a change is identified. For more info please see #12917

@DrewLandgrave
Copy link

DrewLandgrave commented Oct 19, 2017

@brandyscarney, @danbucholtz
Has there been any movement on this?

@HugoHeneault
Copy link

Yeah, another PR which apparently might be more efficient than this one was merged but not yet released. Probably soon with 3.7.2 :)
88b2e83

@fdambrosio
Copy link

a simple virtualscroll is not rendering correctly on iOS9, but it's working on iOS10 & IOS11 & Android.

@Ionitron
Copy link
Collaborator

Hello and thank you for contributing to Ionic! We have been working on porting all of the Ionic components to web components and have recently updated master to reflect this. This significant change has caused this pull request to break. While we really appreciate the time and effort you put into creating this, we are not able to merge it because of the newly introduced conflicts. We are extremely sorry about this. We will not be merging any more features in to v3. If this is a feature and you have the time, please resubmit this PR against the master branch. If this is a critical security issue in v3, we would greatly appreciate it if you would resubmit the PR against the new v3 branch. Thanks so much for your time!

@Ionitron Ionitron closed this Mar 12, 2018
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

Successfully merging this pull request may close these issues.

virtualScroll stops rendering after a certain amount of scroll - solution