avidgoffer
avidgoffer

Reputation: 193

Angular2 Scroll Dropdown Menu w/Arrow Keys

In the following plunk when you click on the Select Market an Observable is populated with an array of data. The first item is highlighted in yellow because it has a property set to selected. When focus is on the input box you can arrow down in the list. The problem is you can arrow down to an item that is clipped by scrollable area. How can I make this item scroll in to view? I think it has something to do with QueryLists, but after a lot of searching online I can't figure out how to implement it properly.

I think in the following code in the ngOnInit in the Market-Search.Component.ts file I need to make the changes:

    this.upDownEvents
      .withLatestFrom(this.markets)
      .subscribe(([event, markets]) => {
          for(let market of markets) {
              if(market.selected) {
                    if(<string>event === 'down' && markets.indexOf(market) < markets.length - 1) {
                        markets[markets.indexOf(market) + 1].selected = true;
                        market.selected = false;
                    }
                    if(<string>event === 'up' && markets.indexOf(market) > 0) {
                        markets[markets.indexOf(market) - 1].selected = true;
                        market.selected = false;
                    }

                  this.markets.next(markets);
                  return;
              }
          }
      });

https://plnkr.co/edit/TBYb5QBau9Vmz8PqQpCl?p=preview

Thank you in advance for any and all help!

Upvotes: 2

Views: 2648

Answers (1)

avidgoffer
avidgoffer

Reputation: 193

I figured this out and wanted to post the answer for anyone else looking for an answer to problem. The answer does lie in using QueryLists and knowing when to use them in the Angular life-cycle. Which is in the ngAfterViewInit event. I've updated the plunk at: https://plnkr.co/edit/TBYb5QBau9Vmz8PqQpCl?p=preview

ngAfterViewInit(): void {
        this.upDownEvents
            .withLatestFrom(this.markets)
            .subscribe(([event, markets]) => {
                for (let market of markets) {
                    if (market.selected) {
                        if (<string>event === 'down' && markets.indexOf(market) < markets.length - 1) {
                            markets[markets.indexOf(market) + 1].selected = true;
                            market.selected = false;

                            let marketItems: MarketItemComponent[] = this.marketItems
                                .filter(x => {
                                    return x.market === markets[markets.indexOf(market) + 1];
                                });

                            if (marketItems.length > 0) {
                                marketItems[0].scrollIntoView();
                            }
                        }
                        if (<string>event === 'up' && markets.indexOf(market) > 0) {
                            markets[markets.indexOf(market) - 1].selected = true;
                            market.selected = false;

                            let marketItems: MarketItemComponent[] = this.marketItems
                                .filter(x => {
                                    return x.market === markets[markets.indexOf(market) - 1];
                                });

                            if (marketItems.length > 0) {
                                marketItems[0].scrollIntoView();
                            }
                        }
                        this.markets.next(markets);
                        return;
                    }
                }
            });
    }

Upvotes: 4

Related Questions