htmlcssangularscroll

Scroll buttons in angular application


[Sorry for my bad English]

I have to create scrollable view, with scroll buttons, like this picture:

Spec:

This is my try:

Template:
<section class="list-with-scroll">

    <div class="list" #list>
        <div *ngFor="let i of items" class="item">{{i}}</div>
    </div>

    <button class="scroller" *ngIf="isOverflown(list)" [class.disable]="!canScrollStart(list)" (click)="scroll(list,-1)" id="scroll-left">&#8678;</button>

    <button class="scroller" *ngIf="isOverflown(list)" [class.disable]="!canScrollEnd(list)" (click)="scroll(list,1)">&#8680;</button>
</section>

Component:

export class AppComponent {
  items = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"];

  isOverflown(element: HTMLElement) {
    return element.scrollWidth > element.clientWidth;
  }

  scroll(element: HTMLElement, direction: number) {
    element.scrollLeft += 100 * direction;
  }

  canScrollStart(element: HTMLElement) {
    return element.scrollLeft > 0;
  }

  canScrollEnd(element: HTMLElement) {
    return element.scrollLeft < element.scrollWidth;
  }
}

CSS:
/* The rest of css see on staclblitz */

#scroll-left{
  order: -1; /* To pevent ExpressionChangedAfterItHasBeenCheckedError */
}

StackBlitz: https://stackblitz.com/edit/my-angular-scroll

The help I need:

Thenk you for any help.


Solution

  • I think I found the best approach: using directive.

    Directive:

    import { Directive, ElementRef, HostListener } from "@angular/core";
    
    @Directive({
      selector: "[appScrollable]",
      exportAs: "appScrollable"
    })
    export class ScrollableDirective {
      constructor(private elementRef: ElementRef) {}
    
      @Input() scrollUnit: number;
    
      private get element() {
        return this.elementRef.nativeElement;
      }
    
      get isOverflow() {
        return this.element.scrollWidth > this.element.clientWidth;
      }
    
      scroll(direction: number) {
        this.element.scrollLeft += this.scrollUnit * direction;
      }
    
      get canScrollStart() {
        return this.element.scrollLeft > 0;
      }
    
      get canScrollEnd() {
        return this.element.scrollLeft + this.element.clientWidth != this.element.scrollWidth;
      }
    
      @HostListener("window:resize")
      onWindowResize() {} // required for update view when windows resized
    }
    

    Usage:

    <section class="list-with-scroll">
    
        <div class="list" appScrollable #list="appScrollable" [scrollUnit]="150">
            <div *ngFor="let i of items" class="item">{{i}}</div>
        </div>
    
        <button id="scroll-left" class="scroller" *ngIf="list.isOverflow"
      [class.disable]="!list.canScrollStart" (click)="list.scroll(-1)">&#8678;</button>
    
        <button class="scroller" *ngIf="list.isOverflow"  [class.disable]="!list.canScrollEnd" (click)="list.scroll(1)">&#8680;</button>
    </section>
    

    stackBlitz: https://stackblitz.com/edit/my-angular-scroll-better