Material Angular scroll to element on mat-list

扶醉桌前 提交于 2020-07-21 00:36:50

问题


I have an Angular Material list with multiple elements, where one of them can be selected.

When I load this list I want to scroll list up to that selected element, to make it more visible. Is there any option?

I was thinking about something like in ngOnInit to check if item is selected, but I have really no idea how to scroll this list up to that item.

Note: not whole page should be scrolled, only the elements on the list.

component.html

<mat-nav-list>
    <mat-list-item *ngFor="let item of items" (click)="itemClick(item)"
        [ngClass]="item.selectedClass">
        {{item.someValue}}
    </mat-list-item>
</mat-nav-list>

component.ts

private itemClick(item: Item): Observable<any> {
    if (item) {
        this.something = item;
        this.items.forEach(item => {
            if (item && item.name === item.name) {
                item["selectedClass"] = "item-selected";
            } else {
                item["selectedClass"] = undefined;
            }
        });
    } else {
        this.something = null;
        this.items.forEach(item => {
                item["selectedClass"] = undefined;
        });
    }

    return of(null);
}

回答1:


Check out this demo: https://stackblitz.com/edit/angular-yjbpoq?file=src%2Fapp%2Fhello.component.ts

The gist is that you attach a new directive to your list and to each of your list items:

<mat-list appScrollable ...>
  <mat-list-item appOffsetTop ...>
  ...
  </mat-list-item>
</mat-list>

The one on the list can set the scrollTop (or use scrollTo, or whatever) for the list:

@Directive({selector: '[appScrollable]'})
export class ScrollableDirective {
  constructor(private _el: ElementRef) {}
  set scrollTop(value: number) { this._el.nativeElement.scrollTop = value; }
}

And the one on the list items can report their offsetTops:

@Directive({ selector: '[appOffsetTop]'})
export class OffsetTopDirective {
  constructor(private _el: ElementRef) { }
  get offsetTop(): number { return this._el.nativeElement.offsetTop; }
}

Each type of directive is accessed in the component via @ViewChild and @ViewChildren:

  @ViewChildren(OffsetTopDirective) listItems: QueryList<OffsetTopDirective>;
  @ViewChild(ScrollableDirective) list: ScrollableDirective;

In the AfterViewInit life cycle hook, the list of items is searched for the one that matches the current selected item (set randomly here for illustration purposes). The list's scrollTop is then set to that item's offsetTop:

  // Inside your component
  selectedItem = Math.floor(Math.random() * 500);
  items = new Array(500).fill(0).map((_, i) => `Item ${i}`);

  ngAfterViewInit() {
    this.list.scrollTop = this.listItems.find((_, i) => i === this.selectedItem).offsetTop;
  }



回答2:


Hard without code, but you can give all your elements an ID, maybe like

Then withngOnInit you can check for your selected element, select the DOM element with document.getElementById('listelement'+elementid) and scroll it into view. Classic JS way to do this would be element.scrollIntoView();



来源:https://stackoverflow.com/questions/54310902/material-angular-scroll-to-element-on-mat-list

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!