PGH
PGH

Reputation: 2204

Image carousel in Angular 6

I need an image carousel for my application (Angular v6). While surfing, I found this solution which uses using ngx-drag-scroll. Is there any other way to do the image carousel like this carousel and display the card component inside it?

Scroll

Can it be achieved without using jQuery and only Typescript?

Upvotes: 10

Views: 17915

Answers (2)

Tom
Tom

Reputation: 5121

angular material card slider

Is there any other way to do the image carousel like this ?

Yes

Without using jquery/javascript,using only Typescript - can I achieve this?

Yes (well TypeScript is a super set of JavaScript and you still need to interact with the DOM but yeah)


Here is a StackBlitz demo of a simple implementation that seems to behave, look and feel like your requirements. (For example you can pass it Material Card components).

It basically works like this: you give the SliderComponent DOM Elements (SliderItemDirectives) and it will add the current most left Element's width to the scroll position of the slider container when you click right. Clicking left subtracts width. I have made use of ContentChildren and ViewChild to get to the widths and scrollLeft property. The animation is achieved with the css scroll-behavior: smooth;.

Here is the main Component:

import { Component, AfterContentInit, ContentChildren, ViewChild, QueryList, ElementRef } from '@angular/core';
import { SliderItemDirective } from './slider-item.directive';

@Component({
  selector: 'app-slider',
  templateUrl: './slider.component.html',
  styleUrls: ['./slider.component.scss']
})
export class SliderComponent implements AfterContentInit {

  @ContentChildren(SliderItemDirective, { read: ElementRef }) items
    : QueryList<ElementRef<HTMLDivElement>>;
  @ViewChild('slides') slidesContainer: ElementRef<HTMLDivElement>;

  private slidesIndex = 0;

  get currentItem(): ElementRef<HTMLDivElement> {
    return this.items.find((item, index) => index === this.slidesIndex);
  }

  ngAfterContentInit() {
    console.log('items', this.items);
  }

  ngAfterViewInit() {
    console.log('slides', this.slidesContainer);
  }

  onClickLeft() {
    this.slidesContainer.nativeElement.scrollLeft -= this.currentItem.nativeElement.offsetWidth;

    if (this.slidesIndex > 0) {
      this.slidesIndex--;
    } 
  }

  onClickRight() {
    this.slidesContainer.nativeElement.scrollLeft += this.currentItem.nativeElement.offsetWidth;

    if (this.slidesIndex < this.items.length - 1) {
      this.slidesIndex++
    }
  }
}

Upvotes: 26

Marko Kacanski
Marko Kacanski

Reputation: 433

There are many solutions that would do what you need, here is the most simple one:

Structure your component something like this:

<component>
  <div class="wrapper">
    <card>
    <card>
    <card>
    ...
    <card>
  </div class="wrapper">
</component>

Use CSS to hide overflow on the x axis of the component, then programmatically add and subtract left margin on the wrapper when buttons are clicked.

You can use @ViewChild to get a hold of the wrapper in your component class so you can manipulate its' CSS values

Upvotes: 0

Related Questions