ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.09k stars 13.51k forks source link

bug: slides issues with async initialization #22961

Closed tpharaoh closed 2 years ago

tpharaoh commented 3 years ago

Bug Report

I have an app using ionic slides (vuejs but I don't think its relavant).

If I reorient phone, pager appears, or resize Safari, pager appears

Ionic version: [x] 5.x

Current behavior: No pager shows on slides image

Expected behavior: Pager should show, as it does in Chrome or when resizing, or re-orienting phone image

Related code: I tried the following methods, and I even tried using the options from the docs

<ion-slides :pager="true">
<ion-slides pager="true">

Ionic info:

ionic info

Ionic:

   Ionic CLI       : 6.12.3 (/usr/local/lib/node_modules/@ionic/cli)
   Ionic Framework : @ionic/vue 5.5.4

Capacitor:

   Capacitor CLI   : 2.4.6
   @capacitor/core : 2.4.6

Utility:

   cordova-res (update available: 0.15.3) : 0.15.2
   native-run                             : not installed

System:

   NodeJS : v12.18.0 (/usr/local/bin/node)
   npm    : 6.14.4
   OS     : macOS Big Sur
liamdebeasi commented 3 years ago

Thanks! Can you reproduce this in an Ionic starter app and provide a link to the repo? I cannot reproduce this on my end.

ionitron-bot[bot] commented 3 years ago

Thanks for the issue! This issue has been labeled as needs reproduction. This label is added to issues that need a code reproduction.

Please reproduce this issue in an Ionic starter application and provide a way for us to access it (GitHub repo, StackBlitz, etc). Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.

If you have already provided a code snippet and are seeing this message, it is likely that the code snippet was not enough for our team to reproduce the issue.

For a guide on how to create a good reproduction, see our Contributing Guide.

tpharaoh commented 3 years ago

I'll put a repo later, but I was finally able to reproduct on starter app, as soon as I added ANY button

<template>
  <ion-page>

    <ion-content :fullscreen="true" scroll-y="false">    
      <div id="container">
        <strong>Ready to create an app?</strong>

        <ion-slides pager="true">
          <ion-slide>
            <ion-card style="border-radius: 25px">

              <ion-card-content>

              A
              </ion-card-content>
            </ion-card>
          </ion-slide>
          <ion-slide>
            <ion-card style="border-radius: 25px">

              <ion-card-content>

              B
              </ion-card-content>
            </ion-card>
          </ion-slide>
        </ion-slides>

        <p>Start with Ionic <a target="_blank" rel="noopener noreferrer" href="https://ionicframework.com/docs/components">UI Components</a></p>
      </div>

       <ion-button
              color="primary"
              shape="round"
              fill="outline"
              size="block"
              >Give Access</ion-button
            >

    </ion-content>
  </ion-page>
</template>

see gist

tpharaoh commented 3 years ago

@liamdebeasi I hope the gist works for you, basically just replacing home.vue from your starter app with that the problem exists.

I did a bunch of further tests, and I was able to solve the problem to my satisfaction, with a small workaround. In my original post I mentioned how re-orienting screen pager would appear, so it led me to think if I disabled the slides element with a property and then enabled on page load it would work.

SO, I added v-if="showReading==true"

I tried to use onMounted to change the value, it didn't work. But with a tiny delay, it did.

onMounted(()=>{
      setTimeout(function(){ showTelemetry.value=true }, 100);
    })

Its a workaround, but it works. As far as I am concerned you can close this...

liamdebeasi commented 3 years ago

Thanks! Yeah Swiper (the library used by ion-slides) definitely has some issues with async initialization, which is what I think is going on here as I was able to get it to break intermittently.

We are currently exploring solutions to better address the async initialization issue.

nvahalik commented 3 years ago

We are also having this problem with Angular. It started when we migrated to v5.

danielmalmros commented 3 years ago

@liamdebeasi we have the same issue within our Ionic Vue app. Swiper is used when the user first open the app - and we got it to work "sometimes" with the Initialization "hack" showed below on iOS and Android - but we still have issues on web where the slider is not loaded on Initialization and we have to refresh 2-3 times before it's loaded.

Ionic slides/swiper seems a bit unstable. I would be happy to provide more information if needed.

Template:

<ion-slides
  v-if="swiperDidInit"
  class="c-slides ion-align-self-center"
  pager="true"
  :options="slideOpts"
>
  <ion-slide v-for="(post, i) in posts" :key="i">
    <ion-card class="c-slide-card">
      <ion-card-content>
        <div class="c-slide-card__img">
          <img :src="post.imageUrl"/>
        </div>
        <div class="c-slide-card__content">
          <ion-card-title class="u-mb--2">{{
            post.title
          }}</ion-card-title>
          <p>
            {{ post.intro }}
          </p>
        </div>
      </ion-card-content>
    </ion-card>
  </ion-slide>
</ion-slides>

Script:

setup() {
  const swiperDidInit = ref<boolean>(false);
  const slideOpts = {
    slidesPerView: 1.25,
    centeredSlides: true,
    spaceBetween: 12,
    init: true,
    speed: 400,
    pagination: {
      el: ".swiper-pagination",
      type: "bullets",
      clickable: true,
    },
    breakpoints: {
      992: {
        slidesPerView: 1,
        spaceBetween: 0,
      },
    },
  };

  onMounted(async () => {
    // Initialization of swiper
    await nextTick(() => {
      swiperDidInit.value = true;
    });
  });
}
seawaywen commented 3 years ago

In our Angular project, we hit the same async initialization issue when use the ion-slides component. we are using: "@ionic/angular": "^5.6.6"

setTimeout() to set the delay can some how resolve the rendering issue, but the delay time value really depends on the context with manual test result. Hope we can have a cleaner production level fix on this soon.

djabif commented 3 years ago

I solved it by updating the IonSlides after the ionSlidesDidLoad occurs.

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

ngAfterViewInit(): void {
  this.slides.ionSlidesDidLoad.subscribe(() => this.slides.update());
}
liamdebeasi commented 2 years ago

Thanks for the issue! With the release of Ionic 6, we made the decision to deprecate ion-slides in favor of using Swiper.js directly.

Moving forward, ion-slides will only receive critical security fixes, and the component will be removed in Ionic 7. As a result, I am going to close this issue.

We have prepared migration guides for each of the 3 JavaScript frameworks we support, so developers can get started migrating right away.

Migration for Angular Migration for React Migration for Vue

We believe this change will lead to a healthier Ionic ecosystem as it frees up resources for the Ionic team to dedicate to other areas of this project while still giving developers options for carousels in their apps. Since ion-slides currently uses Swiper under the hood, the behavior of your carousels should remain the same even after you migrate.

For more information on the reasoning for and benefits of this change, please see the ion-slides documentation.

Thank you!

ionitron-bot[bot] commented 2 years ago

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.