tbranyen / hyperlist

A performant virtual scrolling list utility capable of rendering millions of rows
Other
448 stars 45 forks source link

Is there any port available for Angular 4? #41

Closed naveedahmed1 closed 7 years ago

naveedahmed1 commented 7 years ago

Is there any port of this library available for Angular 4? or do you guys plan to add support for Angular4?

soyuka commented 7 years ago

I'm using this without issues with angular. Just include the script and use bel or some other hypescript library to output DOM.

Oh and when using this, please use changeDetectorRef.detach() and do your change detection manually ^^.

naveedahmed1 commented 7 years ago

Thank you so much for your reply, do you have any code sample available?

soyuka commented 7 years ago

Sure thing.

import { Component, Input, OnDestroy, AfterViewInit, ChangeDetectorRef } from '@angular/core'
import { noop } from '../shared/utils'
import HyperList from 'hyperlist'
import bel from 'bel'

@Component({
  template: `<div id="myList"></div>`,
  selector: 'prefix-hyperlist'
})
export class HyperlistComponent implements AfterViewInit, OnDestroy {
  private virtualList
  private virtualListConfig
  private virtualListContainer
  private list: ListItem[]

  constructor(private cdr: ChangeDetectorRef) {}

  @Input() set list(list: ListItem[]) {
    if (this.virtualList) {
      this.virtualList.destroy()
    }

    this.virtualListConfig = {
          height: 500,
          generate: this.getRow.bind(this),
          total: this.list.length,
          itemHeight: 70
      }

    this.virtualList = new HyperList(this.virtualListContainer, this.virtualListConfig)
  }

  getRow (row) {
    // you don't have to use a table
    // nor do you need to use `bel` you can do `createElement` or use anything that outputs DOM
    const result = bel`
      <tbody>
        <tr>
          <th colspan="3">${this.foo === 'bar' ? 'Foo' : 'Bar'}</th>
          <th colspan="12">Name</th>
        </tr>
        <tr>
          <td colspan="3">${this.foo}</td><td colspan="12">${this.bar}</td>
        </tr>
      </tbody>
      `
    return result
  }

  doSomeStuffWhereYouNeedAngularToRespondToChanges() {
    this.foo = 'bar'
    this.cdr.detectChanges()
  }

  ngAfterViewInit() {
    this.cdr.detach()

    window.onresize = () => {
      if (this.virtualList) {
        // I was changing the height dynamically
        //this.virtualListConfig.height = this.getFormHeight()
        this.virtualList.refresh(this.virtualListContainer, this.virtualListConfig)
      }
    }

    this.virtualListContainer = document.createElement('table')
    this.virtualListContainer.style.display = 'block'

    document.getElementById('myList').appendChild(this.virtualListContainer)
  }

  ngOnDestroy() {
    if (this.virtualList) {
      this.virtualList.destroy()
      this.virtualList = null
    }

    window.onresize = noop
  }
}

Usage:

// I'm using a `getter` on an `input`, usage goes like this:
<prefix-hyperlist [list]="someList | async"></prefix-hyperlist>
naveedahmed1 commented 7 years ago

Its awesome! Thank you so much @soyuka :)

soyuka commented 7 years ago

You're welcome.