dinony / od-virtualscroll

🚀 Observable-based virtual scroll implementation in Angular
https://dinony.github.io/od-vsstatic/
MIT License
134 stars 12 forks source link

[feature request] Iterable support #2

Open buu700 opened 7 years ago

buu700 commented 7 years ago

Currently vsData is expected to be Observable<any[]>. It'd be useful if it were expanded to support the more general Observable<Iterable<any>>, which would allow it to take such types as ES6 Maps and Sets and Immutable.js data structures.

buu700 commented 7 years ago

Just wanted to add, I ended up arriving on a pattern that works pretty well with the current API. I needed a way to access other inputs to my component from within the list items, and the solution I came up with seems to work pretty well while also making the Observable<any[]> vs Observable<Iterable<any>> issue irrelevant.

@Input() public immutableList: List<Thing>;

@Input() public otherInput: string;

public readonly vsData  = new Subject<{
    immutableList: List<Thing>;
    otherInput: string;
}[]>();

public ngOnChanges () : void {
    this.vsData.next(new Array(this.immutableList.size).fill({
        immutableList: this.immutableList,
        otherInput: this.otherInput
    }));
}

public vsEqualsFunc () : boolean {
    return false;
}

---

<od-virtualscroll
    fxFlexFill
    [vsData]='vsData'
    [vsEqualsFunc]='vsEqualsFunc'
    [vsOptions]='vsOptions'
>
    <ng-template let-item let-row='row'>
        <my-list-item
            [thing]='item.immutableList.get(row)'
            [otherInput]='item.otherInput'
        ></my-list-item>

        <div *ngIf='(row + 1) === item.messages.size'>
            This is the end of the list.
        </div>
    </ng-template>
</od-virtualscroll>
dinony commented 7 years ago

Hey, thanks for the update. Ok, it's still a little bit of wrapping but with your pattern you can avoid converting between immut List<any> -> any[]. I will still look into the ES6 iterable interface - I'd imagine that Observable<any[]> | Obervable<Iterable<any>> could be handy.

buu700 commented 7 years ago

Cool, sounds good. Iterable<T> is a subset of T[] (if I'm not mistaken), so I think it'll be a fairly small change — you shouldn't need the union type, and the existing logic should continue to work with either no changes or a const arr = typeof iterable === 'array' ? iterable : Array.from(iterable).

re: that pattern, just to clarify, it was really only about making values other than the main list accessible from within the template; resolving the iterable vs array issue was incidental. (I'm not super familiar with <ng-template> though, so it's possible that Angular already provides a more idiomatic way to do this.)