Ionic-framework: bug: ion-slides regression in modals (unusable after 4.11.0)

Created on 11 Oct 2019  路  35Comments  路  Source: ionic-team/ionic-framework

Bug Report

Ionic version:

4.11.0

Current behavior:
ion-slides now behaves strangely when placed in modals after v4.11.0, touch events aren't correctly handled and scrolling is not working, as well as layout is stretched with incorrect dimensions calculation.

v4.10.3 is working correctly.

Expected behavior:
It should work as before

Steps to reproduce:
Put an ion-slides with 2 or 3 photos in a modal page and present it, try to drag left or right, you will get stuck between photos.

Other information:

Ionic info:

Ionic:

   Ionic CLI                     : 5.4.2 (/usr/local/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.11.0
   @angular-devkit/build-angular : 0.801.3
   @angular-devkit/schematics    : 8.1.3
   @angular/cli                  : 8.1.3
   @ionic/angular-toolkit        : 2.0.0

Cordova:

   Cordova CLI       : 9.0.0 ([email protected])
   Cordova Platforms : android 8.1.0
   Cordova Plugins   : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 4.1.2, (and 12 other plugins)

Utility:

   cordova-res : 0.6.0 (update available: 0.8.0)
   native-run  : 0.2.8 

System:

   Android SDK Tools : 26.1.1 (/Users/omardoma/Library/Android/sdk)
   ios-deploy        : 1.9.4
   ios-sim           : 8.0.2
   NodeJS            : v10.16.3 (/usr/local/Cellar/node@10/10.16.3/bin/node)
   npm               : 6.9.0
   OS                : macOS Mojave
   Xcode             : Xcode 11.1 Build version 11A1027
core bug

Most helpful comment

Would love to hear some news on this.

@NikolaDeveloper Here's a one line fix / workaround for React:

// ...
<IonSlides onIonSlidesDidLoad={function(this: any){this.update()}}>
//...

It basically just calls update on IonSlides after loading. It's nice because it doesn't need any ref or additional variable.

All 35 comments

Thanks for the issue. Can you provide a repo with the code required to reproduce this issue? The 4.11.0 release just had Ionic React changes, so nothing in your Ionic Angular app should be different.

Sorry for the late reply, I have prepared a StackBlitz demo with my current code: https://stackblitz.com/edit/ionic-v4-slides-modal-bug

However what's weird is that the bug happens non-deterministically, sometimes it happens, sometimes it doesn't, If I had to make a guess, then I would say something is blocking the slides from loading and firing the ionSlidesDidLoad event, that's why the swiping functionality and the layout is messed up.

I will investigate further and post my findings, till then please let me know if there is anything else I can help with in debugging it.

Thanks for the follow up. I am unable to reproduce this issue using the repo you provided. Is this happening on a particular platform (iOS vs Android)?

Well it happens on all platforms (Browser, iOS & Android), basically what happens is, sliding becomes very glitchy, and the slides size becomes very expanded.

I believe a new issue #19641 refers to the same problem happening on React.

Are there any particular steps to reproduce that I should be following? I am still unable to reproduce the issue using the StackBlitz.

I can confirm the bug with the StackBlitz example as I am also affected by the linked issue for the react package.

Unfortunately, the error really occurs randomly and cannot really be reproduced . You can try to swipe back and forward several times with e.g. pressed mouse button, close modal and open it again and redo some swiping. Repeat the process multiple times until the bug appears.

Example where it happens after the first try:
23-10-_2019_14-28-45

Thank you @SimonGolms for taking the time to illustrate the bug, @liamdebeasi this is indeed what is happening, and as I said its very random, however it happens quite a lot, its actually the issue that is holding me back from upgrading past v4.10.3, as my app is heavily relying on slides as it contains a lot of media.

If there is anything we can do to help you debug it more, please let us know!

One thing to note is that the bug can be fixed whenever it occurs by simply triggering a window resize

We're seeing this issue as well. Oddly if we switch our tsconfig's target to es5 instead of es2015 it seems to work consistently.

@marpstar That's really weird. In my case, I can't really change the target to es5 because I am using Angular 8 and its differential loading, so doing so will disable it.

@omardoma I agree that switching back to ES5 isn鈥檛 ideal. I鈥檇 like to see this fixed but thought the ES5 tidbit was worth mentioning for anyone who tries to fix.

@marpstar Yeah definitely, thanks a lot for mentioning that, will fallback to it if the issue wasn't fixed quickly!

@liamdebeasi Any update on this issue, please? We really want to update our Ionic version to the latest to get some bug fixes we need, but this issue is holding us back

One thing to note is that the bug can be fixed whenever it occurs by simply triggering a window resize

Good hint. I was able to fix it with the following exemplary workaround for my use case.

// slides-modal.component.html
...
<ion-content>
  <ion-slides #sliderRef>
    <ion-slide>
       ...
    </ion-slide>
  </ion-slides>
</ion-content>
...
// slides-modal.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { ModalController, IonSlides } from '@ionic/angular';

@Component({
  selector: 'app-slides-modal',
  templateUrl: './slides-modal.component.html',
  styleUrls: ['./slides-modal.component.scss']
})
export class SlidesModalComponent implements OnInit {

  @ViewChild('sliderRef', { static: true }) protected slides: IonSlides;

  constructor(private modalController: ModalController) {}

  ngOnInit() {
    this.slides.update();
  }
}

_Edit: In case this workaround don't work, check this one._

Hi everyone,

I was able to reproduce this issue. I will look into this a bit more. Thanks!

I was able to reproduce this bug in Ionic 4.10.0, so it doesn't seem like a 4.11 regression. I'm going to dig into this a bit more and see where the bug originally appeared.

Great, thanks for looking into that, feel free to rename the issue's title if it applies in 4.10.x as well. I named it this way because it never happened with me except past 4.11.x

One thing to note is that the bug can be fixed whenever it occurs by simply triggering a window resize

Good hint. I was able to fix it with the following exemplary workaround for my use case.

// slides-modal.component.html
...
<ion-content>
  <ion-slides #sliderRef>
    <ion-slide>
       ...
    </ion-slide>
  </ion-slides>
</ion-content>
...
// slides-modal.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { ModalController, IonSlides } from '@ionic/angular';

@Component({
  selector: 'app-slides-modal',
  templateUrl: './slides-modal.component.html',
  styleUrls: ['./slides-modal.component.scss']
})
export class SlidesModalComponent implements OnInit {

  @ViewChild('sliderRef', { static: true }) protected slides: IonSlides;

  constructor(private modalController: ModalController) {}

  ngOnInit() {
    this.slides.update();
  }
}

Awesome, will workaround it this way then until its fixed, thanks man.

FWIW that workaround doesn't work for me.

Any progress being made on this?

My issue is slides will not swipe in a modal when it is first opened. Open the modal again, the slides works.

Following the above suggest, I solved the issue simply by adding a .update() call:

slides.update();

Don't know why.

@netsesame2 thanks for the hint, looks like it worked for me

+1 to this issue tho
I'm having this on React. Doesn't work on iOS but does in browser

I have found this issue without the modal use case, just simple routing back and forth.

After trying ChangeDetectorRef or @SimonGolms solution without success I have added a ngIf to my slider-wrapper and set the variable to true on AfterContentCheckedand it worked without hiccups.

Haven't tried on previous hooks.

I'm having this issue as well. I'm using React 4.11.7, and in addition to the sliding problem, I also have a problem where sometimes the slide simply will not work at all. I can swipe and it emits the onIonSlideNextStart / ...PrevStart events but the slide itself does not change.

Any chance of this getting fixed?

Why is nobody from the Ionic team even acknowledging that this problem needs resolution?

Hi,

I am hiding your comment as it is off topic and not constructive to getting this issue resolved. I will try to take a look at this issue this week.

We have acknowledged this is an issue here. We are looking into a resolution; however, since it appears randomly it is a bit tricky to resolve. Additionally, a few users on this thread have provided temporary workarounds. I will post another update here when I have more information to share.

Thanks!

Hi @liamdebeasi, any news regarding this bug?
I noticed that after calling modal.present() several times with a <ion-slides> component, the nested <ion-slide> elements are not handled correctly. In case this bug appears, swiper.length() returns 0. During debugging I also noticed that the bug occurs more often when I use <ion-content fullscreen="true"> in my component.

While my first workaround unfortunately didn't really work, I want to share another possible workaround, were I was not able to reproduce the bug after intensive testing.

// slides-modal.component.html
...
<ion-content>
  <ion-slides #sliderRef></ion-slides>
</ion-content>
...
// slides-modal.component.ts
import { Component, OnInit, ViewChild } from '@angular/core';
import { ModalController, IonSlides } from '@ionic/angular';

@Component({
  selector: 'app-slides-modal',
  templateUrl: './slides-modal.component.html',
  styleUrls: ['./slides-modal.component.scss']
})
export class SlidesModalComponent implements OnInit {

  @ViewChild('sliderRef', { static: true }) protected slides: IonSlides;

  src = './assets/img.png'
  constructor(private modalController: ModalController) {}

  async ngOnInit() {
    const swiper = await this.slides.getSwiper();
    swiper.appendSlide(`<ion-slide><img src="${this.src}"/></ion-slide>`);
    ...
  }
}

Is there any workaround for react?

Would love to hear some news on this.

@NikolaDeveloper Here's a one line fix / workaround for React:

// ...
<IonSlides onIonSlidesDidLoad={function(this: any){this.update()}}>
//...

It basically just calls update on IonSlides after loading. It's nice because it doesn't need any ref or additional variable.

Fixed it with the ionViewDidEnter hook instead:

ionViewDidEnter () {
  this.slides.update();
}

For anyone that's interested, with @ionic/angular 5.2.1, I had to change the workaround to the following for pagination to work on the second load of the modal. Looks like you have to use ElementRef<IonSlides> instead of using IonSlides directly with ViewChild. Took me a couple days to figure this out so I'm posting in case anyone else is stuck on it.

template:

<ion-slides pager="true" #sliderRef>

component:

@Component({
  selector: 'app-slidesmodal',
  templateUrl: 'slidesmodal.page.html',
  styleUrls: ['slidesmodal.page.scss'],
})
export class SlidesModalPage {
  @Input() modalController: ModalController
  @ViewChild('sliderRef') slides: ElementRef<IonSlides>;

  constructor(
  ) {}

  ionViewDidEnter() {
    this.slides.nativeElement.update();
  }
}

ionic info:

Ionic:

   Ionic CLI                     : 6.10.1
   Ionic Framework               : @ionic/angular 5.2.1
   @angular-devkit/build-angular : 0.901.8
   @angular-devkit/schematics    : 9.1.7
   @angular/cli                  : 9.1.8
   @ionic/angular-toolkit        : 2.2.0

Capacitor:

   Capacitor CLI   : 2.2.1
   @capacitor/core : 2.3.0

Utility:

   cordova-res (update available: 0.15.1) : 0.14.0
   native-run                             : 1.0.0

System:

   NodeJS : v12.17.0
   npm    : 6.14.5
   OS     : macOS Catalina

@kheftel If you have only one ion-slides in your component, you can do that to get IonSlides without ElementRef :

@ViewChild(IonSlides) slides: IonSlides;

ionViewWillEnter() {
    this.slides.update()
}

@kheftel If you have only one ion-slides in your component, you can do that to get IonSlides without ElementRef :

@ViewChild(IonSlides) slides: IonSlides;

ionViewWillEnter() {
  this.slides.update()
}

I tried that first, but, sadly it didn't work and my slides variable was still an ElementRef, and iirc its nativeElement didn't have an update function. At any rate this.slides.update() was not a function.

We stumpled upon something like this these days, using Ionic+Angular. Rendering an ion-slides inside a modal causes the ion-slides component to be rendered wrong.

More specifically, the slides are rendered "centered" inside the ion-slides. We have three slides, so we see the second one in the screen (slightly misplaced), and inspecting the dom the first slide is on the left, outside the screen.

We are sliding the slides programamtically using buttons, and they work, but they are rendered completely out of place.

The slides.update trick did not solve the issue.

Hiding the slides with *ngIf and showing them after ionViewDidEnter rendered them correctly, but they still flash rendered bad before being rendered good, which is quite ugly.

This seems to be related to the slides being rendered while outside the view or in a moment where they can not access the correct view size (just as hypotesis, i'm not completely sure about this).

EDIT: We found the beforementioned *ngIf workaround HERE

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brandyscarney picture brandyscarney  路  3Comments

SebastianGiro picture SebastianGiro  路  3Comments

fdnhkj picture fdnhkj  路  3Comments

BilelKrichen picture BilelKrichen  路  3Comments

danbucholtz picture danbucholtz  路  3Comments