Skip to content

Implement element size/position/visible event or a general read/write queue again #1693

@mhevery

Description

@mhevery

Purpose

A component should be able to read its size and react to it. This is hard because we have to wait until DOM is fully rendered before causing layout and reading its position. (Additionally the browser does not have a resize event on elements)

Mental Model

A component can register a size host event which the framework will call:

  1. On initial render of the component to supply the initial size information.
  2. When component size changes.

Component may change size due to:

  1. Window resize
  2. Changes to DOM rendering (ie text gets longer cause reflow.)

Algorithm

  1. dirty check all host elements which have size using Element.getBoundingClientRect() at the end of digest cycle when:
    • any DOM rendering occurs (may do pruning if we know that some things are absolutely position, later optimization)
    • a Window resize occurs. (orientation on mobile, which should cause a resize)
  2. Invoke size handler only if the bounding rectangle has changed.
  3. Schedule another digest before end of the turn. (This can be done be creating a Promise and resolving it within current digest.)

Notes

  • Other platforms may have this primitives and we don't have to dirty check
  • Benefit of having it as event is that we can do proper batching of layouts.
  • We can optimize (prune) dirty checking later once we know more about the application structure.
  • Ruler Service can now be deleted.
  • Need to split the size event and position concern into separate events.
  • Events:
    • size: when width/height has changed. (Size changes less often then position)
    • position: when width/height or position changed.
    • visible: when the component is visible on the screen.

Example

@Component({
  selector: '...'
})
@View({
  template: `
  <ul style="overflow: scroll" 
        (scroll)="onScroll($event.target.scrollTop)"
        (size)="onResize($event)" >
    <li [style.height.px]="topPadding"></li>
    <li *for="var row in visibleRows"></li>
    <li [style.height.px]="bottomPadding"></li>
  </ul>
`
})
class VirtualScroll {
  visibleRows: Array;
  topPadding: number;
  buttomPadding: number;

  onScroll(offset: number) {
    // update the visibleRows
  }

  onResize(rect:Rectangle) {  
    // compute the number of visible rows.
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions