Search code examples
javascriptangulartypescriptngx-gallery

Can't swap images in a ngx-gallery


I'm having a little issue using ngx-gallery Here is the github page and my stackblitz example.

Scenario - I want my user click a button to swap the images around to the first image in the gallery.

Ex. User clicks button and moves the image from position 3 to image position 1. Including the small thumbnail, the medium image (main viewer) and the big preview image.

Problem - Everything I've tried doesn't seem to work. I can't really find any methods that swap the indexes and when I swap them manually nothing happens.

FYI - I can add and delete images to the viewer with push and pop, I just can't set (swap) the first image programmatically with another.

stackblitz example

Here is some of the examples I've tried.

export class AppComponent implements OnInit {
  @ViewChild('gallery') gallery: NgxGalleryComponent;
  galleryOptions: NgxGalleryOptions[];
  galleryImages: NgxGalleryImage[];

  constructor() {}

  ngOnInit() {
    this.galleryOptions = [{
        width: '600px',
        height: '400px',
        thumbnailsColumns: 4,
        arrowPrevIcon: 'fa fa-chevron-left',
        arrowNextIcon: 'fa fa-chevron-right',
        imageAnimation: NgxGalleryAnimation.Slide
      }
    ];

    this.galleryImages = [{
        small: 'https://preview.ibb.co/jrsA6R/img12.jpg',
        medium: 'https://preview.ibb.co/jrsA6R/img12.jpg',
        big: 'https://preview.ibb.co/jrsA6R/img12.jpg'
      },
      {
        small: 'https://preview.ibb.co/kPE1D6/clouds.jpg',
        medium: 'https://preview.ibb.co/kPE1D6/clouds.jpg',
        big: 'https://preview.ibb.co/kPE1D6/clouds.jpg'
      },
      {
        small: 'https://preview.ibb.co/mwsA6R/img7.jpg',
        medium: 'https://preview.ibb.co/mwsA6R/img7.jpg',
        big: 'https://preview.ibb.co/mwsA6R/img7.jpg'
      }, {
        small: 'https://preview.ibb.co/kZGsLm/img8.jpg',
        medium: 'https://preview.ibb.co/kZGsLm/img8.jpg',
        big: 'https://preview.ibb.co/kZGsLm/img8.jpg'
      },
    ];
  }

  swap() {
    console.log("button clicked!");

    // doesn't do anything
    [this.galleryImages[2], this.galleryImages[0]] = [this.galleryImages[0], this.galleryImages[2]];

    // doesn't do anything
    [this.gallery.thumbnails.images[2], this.gallery.thumbnails.images[0]] = [this.gallery.thumbnails.images[0], this.gallery.thumbnails.images[2]];

    // doesn't do anything
    [this.gallery.images[2], this.gallery.images[0]] = [this.gallery.images[0], this.gallery.images[2]];
  }

}
<div class="gallery-wrapper">
  <ngx-gallery #gallery [options]="galleryOptions" [images]="galleryImages" class="ngx-gallery"></ngx-gallery>
</div>

<button (click)="swap()">swap image 1 and 3</button>


Solution

  • This may be because you are mutating the array. Sometimes Angular change detection only kicks in when you do not mutate.

    Mutating happens when you change the array (the items in the array or the order of items in the array) but do not change the array reference.

    To avoid mutating try:

    this.galleryImages = [this.galleryImages[2], this.galleryImages[1], this.galleryImages[0]]
    

    Alternatively, even when you do mutate an Array you can solve the problem by running lodash cloneDeep afterwards, which will get you a new reference after mutating:

    import { cloneDeep } from 'lodash-es'
    
    // your existing code
    this.galleryImages = cloneDeep(this.galleryImages)
    

    Note that there are some decent npm packages for changing the position of items in an array such as array-move - this avoids mutation - note there are other good packages for this too, look for competitors on npm trends