Last version swiper v9: loadPrevNext module lazy not included!

I see my loadPrevNext in lazy was not working anymore since last f7 update, and I see swiper v9 has eliminated this useful feature in the latest release for lazy module!

anyway to make this feature this work again? is this included in f7 last version? because it is not working anymore as before!

this was working before!

    lazy: {
      enabled: true,
      loadPrevNext: true,
      loadPrevNextAmount: 2,
      loadOnTransitionStart: false,
      threshold: 50,
    },

this issue also mentioned here or something changed?

any ideas to make loadPrevNext and loadPrevNextAmount work again?
thanks!

here => patient-monad-u3oi5y - CodeSandbox

1 Like

Hi thank you for your reply but the problem comes when you use it with

slidesPerView: 'auto',

and you use this in html

<div class="swiper-slide swiper-lazy" loading="lazy" data-background="https://swiperjs.com/demos/images/nature-${++i}.jpg"></div>

I need the image inside the swiper-slide not as img, because inside the swiper-slide is my card content!

Also I am having issues with click propagation when swiping to new slide has you tried like this? and I am using

      preventClicks: true,
      preventClicksPropagation: true,

Try it and you will see the next prev slides does not load!

<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="left"><a href="#" class="link back"><i class="icon icon-back"></i><span class="if-not-md">Back</span></a></div>
        <div class="title">Swiper</div>
      </div>
    </div>
    <div class="page-content">
      <div class="swiper stores stores-auto">
        <div class="swiper-wrapper">${[...Array(10).keys()].map(i => $h`
            <div class="swiper-slide swiper-lazy" loading="lazy" data-background="https://swiperjs.com/demos/images/nature-${++i}.jpg">
          </div>`)}
        </div>
        <div class="swiper-button-next"></div>
        <div class="swiper-button-prev"></div>
        <div class="swiper-pagination"></div>
      </div>
    </div>
  </div>
</template>
<script>
export default (_,{ $, $el, $f7, $onMounted }) => {
  $onMounted((p = $el.value) =>
    Array.from(p.find('.swiper')).map(i => $f7.swiper.create(i,{
      lazy: true,
      prevNext: 2,
      slidesPerView: 'auto',
      spaceBetween: 5,
      centeredSlides: false,
      preventClicks: true,
      preventClicksPropagation: true,
      navigation: {
        nextEl: p.find('.swiper-button-next'),
        prevEl: p.find('.swiper-button-prev'),
      },
      on: {
        init: (s) => s.emit('slideChange'),
        click: function (swiper, e) {
            console.log('swiper click');
            e.preventDefault();
        },
        tap: function (swiper, e) {
          console.log('swiper tap');
          e.preventDefault();
        },
        touchStart: function (swiper, e){
          console.log('swiper touchStart');
          e.preventDefault();
        },  
        touchMove: function (swiper, e){
          console.log('swiper touchMove');
          e.preventDefault();
        },
        touchEnd: function (swiper, e){
          console.log('swiper touchEnd');
          e.preventDefault();
        },
        observerUpdate: function (swiper, e) {
          console.log('swiper observerUpdate');
        }, 
        slideChange: (s, v = s.params.prevNext, x = s.activeIndex, a = s.slides) =>
          a.slice(Math.max(x-v,0),++x+v).forEach(i => $(i).find('img').removeAttr('loading'))
      }
      
    })).forEach(i => p.once('page:beforeremove',() => i.destroy()))
  );
  return $render;
};
</script>


<style>
.swiper {
  width: 100%;
  height: 245px;
}
.sswiper-slide img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  -ms-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  position: absolute;
  left: 50%;
  top: 50%;
}

  .swiper-slide {
    width: 95%;
    background-size: cover;
    background-position: center;
    margin-left: auto;
    margin-right: auto;
    font-weight: 300;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #fff;
    color: #000;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    background-size: cover;
    background-position: center;
  }

  
</style>

any ideas how to fix these things?

in my case the next slide is not loading until I swipe to that slide!

Here another example showing the next prev load problem with auto slides!
I need the image to be inside the slide using data-background so I can put content inside the slide! in this sample I just put a text in reality it is a card! same issue not loading the next or prev images as I need so user can see the part of the next slide before swiping!

see here again!

<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="left"><a href="#" class="link back"><i class="icon icon-back"></i><span class="if-not-md">Back</span></a></div>
        <div class="title">Swiper</div>
      </div>
    </div>
    <div class="page-content">
      <div class="swiper stores stores-auto">
        <div class="swiper-wrapper">${[...Array(10).keys()].map(i => $h`


          <div class="swiper-slide swiper-lazy" data-background="https://swiperjs.com/demos/images/nature-${++i}.jpg">
                <div class="container">slide ${i}</div>
                <div class="swiper-lazy-preloader"></div>
          </div>

          `)}
        </div>
        <div class="swiper-button-next"></div>
        <div class="swiper-button-prev"></div>
        <div class="swiper-pagination"></div>
      </div>
    </div>
  </div>
</template>
<script>
export default (_,{ $, $el, $f7, $onMounted }) => {
  $onMounted((p = $el.value) =>
    Array.from(p.find('.swiper')).map(i => $f7.swiper.create(i,{
      lazy: true,
      prevNext: 2,
      slidesPerView: 'auto',
      spaceBetween: 5,
      centeredSlides: false,
      preventClicks: true,
      preventClicksPropagation: true,
      navigation: {
        nextEl: p.find('.swiper-button-next'),
        prevEl: p.find('.swiper-button-prev'),
      },
      on: {
        init: (s) => s.emit('slideChange'),
        click: function (swiper, e) {
            console.log('swiper click');
            e.preventDefault();
        },
        tap: function (swiper, e) {
          console.log('swiper tap');
          e.preventDefault();
        },
        touchStart: function (swiper, e){
          console.log('swiper touchStart');
          e.preventDefault();
        },  
        touchMove: function (swiper, e){
          console.log('swiper touchMove');
          e.preventDefault();
        },
        touchEnd: function (swiper, e){
          console.log('swiper touchEnd');
          e.preventDefault();
        },
        observerUpdate: function (swiper, e) {
          console.log('swiper observerUpdate');
        }, 
        slideChange: (s, v = s.params.prevNext, x = s.activeIndex, a = s.slides) =>
          a.slice(Math.max(x-v,0),++x+v).forEach(i => $(i).find('img').removeAttr('loading'))
      }
      
    })).forEach(i => p.once('page:beforeremove',() => i.destroy()))
  );
  return $render;
};
</script>


<style>
.swiper {
  width: 100%;
  height: 245px;
}
.sswiper-slide img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 100%;
  -ms-transform: translate(-50%, -50%);
  -webkit-transform: translate(-50%, -50%);
  -moz-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  position: absolute;
  left: 50%;
  top: 50%;
}

.swiper-lazy{
 width: 600px;
  height: 300px;
  border: 1px solid green;
  background-size: cover;
}

  .swiper-slide {
    width: 95%;
    background-size: cover;
    background-position: center;
    margin-left: auto;
    margin-right: auto;
    font-weight: 300;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #fff;
    color: #000;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    background-size: cover;
    background-position: center;
  }

  
</style>


also if you add effect cards to the slides this code above the previous and next slide are loaded without problems! so I think it might be an issue with using data-background with images somewhere or a bug in swiper using data-background!

  effect: 'cards',

thanks for any tips!

mine wasn’t v9 (now it is => patient-monad-u3oi5y - CodeSandbox)
you’re not really using v9 (you don’t.)
make sure you really use v9 (only v9)

data-background is not supported in v9(f7-v8)

native lazy-loading works only on img (and iframe).
it doesn’t work with css background-image

you need to implement it by yourself

bottom line: you don’t really use lazy-loading.
‘virtual-slide’ is more appropriate for your case => lucid-rain-x8yqbn - CodeSandbox

I have installed the las version of f7 that comes with swiper latest version! or did you add swiper manually using “npm i swiper”?

Also there is an issue with click propagation when you use “swiper-init” in your html, when swiping to the next slide always click is propagated, when you create the swiper

$f7.swiper.create('.swiper.stores', {...

this will init the swiper and will show everything OK, no click propagation then after you need to filter slides (stores opened for instance etc…) and need to update the slide content again using

swiper.update(); 

then the background image is not loading anymore only text content is updated and showing correctly!

If you init again the swiper to refresh properly the lazy loading images then when swiping appears the problem again with click propagating when swiping making this an annoying behaviour if you have elements with click inside your slides!

Try to update your slides after swiper has been loaded and see what happens with the click propagation and use images as background lazy not working anymore after you update the content!

I use also

observer: true,
preventClicks: true,
preventClicksPropagation: false,

and same issue all the time!

In my case Framework 7 version shows

# framework7 -V
7.0.1

which version are you using?
thanks!

framework7 -V means: framework7-cli

i’m using f7-v7.1.5 (and v8.beta)

if you’re using ‘latest’ then it’s v7.1.5

v7.1.5 real dep is swiper-v8.4.5:

"node_modules/framework7": {
  "version": "7.1.5",
  "resolved": "https://registry.npmjs.org/framework7/-/framework7-7.1.5.tgz",
  "integrity": "sha512-zO+0Q9SSkWitnFEdwqVmFQ+uOyZ06ERuax0fYyUozwhTYQhc5v9LjimC97+irQrkOetXq3ZKVn064q9tv/Wv4g==",
  "dependencies": {
    "dom7": "^4.0.6",
    "htm": "^3.1.1",
    "path-to-regexp": "^6.2.1",
    "skeleton-elements": "^4.0.1",
    "ssr-window": "^4.0.2",
    "swiper": "^8.4.5"
  },
  "funding": {
    "type": "patreon",
    "url": "https://www.patreon.com/framework7"
  }
}

not clear what is your issue with ‘clicks’ and how is’t related to ‘lazy’
i’ll make some tests and let you know.

seems ok => romantic-violet-8htn2d - CodeSandbox

loadPrevNext => romantic-violet-8htn2d - CodeSandbox

I will make a sample to let you know the problem! thanks!! Try using auto slides and slides with images in swiper that shows a tiny edge part of the next slide on the viewport, then try make lazy load to load the image of the second slide before swiping then after swiper is initialized update the content in the slides, create a click button that loads a new content for the slides, try to update the content with swiper.update();

you will see the images are not being lazy loading again only the content inside the slider is updated.

if you try to re-create the slider again after the content has been updated to see if this way the images load then you init() the slider again with the same parameters options as before, but doing so, this create a click propagation problem when you swipe to the next slide! this behavior does not happen when you create the slides the first time!

also do not know why updating the slide content does not work for images!

add these options below to see in the console when you swiping or clicking and see if it is working properly with the correct behaviour!

        observer: true,
        slidesPerView: 'auto',
        spaceBetween: 5,
        centeredSlides: false,
        preventClicks: true,
        preventClicksPropagation: true,
on: {
          init: function (s) {
            console.log('swiper init');
            s.emit('slideChange');
          },
          click: function (swiper, e) {
              console.log('swiper click');
              e.preventDefault();
              console.log('clickSlide');
          },
          tap: function (swiper, e) {
            console.log('swiper tap');
            e.preventDefault();
          },
          touchStart: function (swiper, e){
            console.log('swiper touchStart');
            e.preventDefault();
          },  
          touchMove: function (swiper, e){
            console.log('swiper touchMove');
            e.preventDefault();
          },
          touchEnd: function (swiper, e){
            console.log('swiper touchEnd');
            e.preventDefault();
          },
          observerUpdate: function (swiper, e) {
            console.log('swiper observerUpdate');
          }, 
          afterInit: (swiper) => {
            console.log('swiper afterInit');
          },

when the click is being propagation by swiping to next slide it is an issue that occurs when using “swiper-init” in the html or when init again the slider with the same parameters as before when you created!

This means init() by second time generate this click propagation problem! and when you update slides that has a background image the image is not being updated only the content!

///////

I delete by the way framework7 and reinstalling using

npm install -g framework7-cli --unsafe-perm=true --allow-root

after I did

# framework7 -V
7.0.1

I think 7.0.1 it is the CLI version because in the npm_modules/framwork7/package.json
it says:

 "name": "framework7",
  "version": "7.1.5",
  "description": "Full featured mobile HTML framework for building iOS & Android apps",
  "type": "module",
  "exports": {

so I think I am using the latest version too!!

you do. (but swiper is v8.4.5)
7.0.1 is f7-cli

loadPrevNext works correctly => romantic-violet-8htn2d - CodeSandbox

the show the next slide problem I solved using this too

        lazy: {
            checkInView: false,
            enabled: true,
            loadPrevNext: true,
            loadPrevNextAmount: 2,
            loadOnTransitionStart: false,
            scrollingElement: '',
            elementClass: 'swiper-lazy',
            loadingClass: 'swiper-lazy-loading',
            loadedClass: 'swiper-lazy-loaded',
            preloaderClass: 'swiper-lazy-preloader'
        },

Try using auto slides!

        slidesPerView: 'auto',

then try to update the slider or filter the slider content with new content and see what happens!

click is propagating again when you init() slider again or call create swiper again! and if you update the slider with new content the images not being loaded again!

and if you have set these options below in the parameters they do not work after reinit the swiper again! click propagation start happening!

        preventClicks: true,
        preventClicksPropagation: true,

did you update swiper manually? or you are using framework7 7.0.1 with swiper 8.4.5 like me?

we both use the same versions.

f7-cli => 7.0.1 (f7-cli is not related to your issue)
f7 => 7.1.5
swiper => 8.4.5

keep in mind that you don’t really use swiper v9.

everything works correctly
i dont understand what is the issue (or what are you doing),
i need to see your code to understand what’s going on.

this his how my slides looks like! they have clickable areas inside! all these area working fine the first time when swiper is initialised, then after I make any update to the slider content the content does not load anymore the images in this case for instance new stores are now online and they need to show up in the slider after refresh etc…

As you see, the use of images as a background was working fine until last update of swiper also handy to have content inside the slider!

when you reinit swiper let is say after an update of the content then the click propagation problems shows you swipe and every time you swipe to next slide a click is being propagating along with the swipe!

in my case I have clickable elements over the slide, over the top right and bottom left! and these have not to be propagating while swiping only when I click or tap on them!

add this to the slider parameters!

on: {
            init: function (s) {
              console.log('swiper init');
              s.emit('slideChange');
            },
            click: function (swiper, e) {
                console.log('swiper click');
                e.preventDefault();
                alert('clickSlide');
            },
            tap: function (swiper, e) {
              console.log('swiper tap');
              e.preventDefault();
            },
            touchStart: function (swiper, e){
              console.log('swiper touchStart');
              e.preventDefault();
            },  
            touchMove: function (swiper, e){
              console.log('swiper touchMove');
              e.preventDefault();
            },
            touchEnd: function (swiper, e){
              console.log('swiper touchEnd');
              e.preventDefault();
            },
            observerUpdate: function (swiper, e) {
              console.log('swiper observerUpdate');
            }, 
            afterInit: (swiper) => {
              console.log('swiper afterInit');
            },

I will make the code and post it here to show you the problem!
thanks for your prompt reply ever!

update works ok => romantic-violet-8htn2d - CodeSandbox

i’m gonna stop here,
trying to guess what you are doing without your code, it’s really hard.

1 Like

last update of swiper was at 2022-12-16 (with f7-v7.1.1)

everything seems ok,
but if you think there is an issue with swiper v8.4.5,
then try to downgrade f7 to v7.0.9 (swiper v8.1.4) and see what happen.

here the code sample

there is a loading store… message before stores show, then every slide after stores are loaded have clickable links in this sample top left and top right area links.

when you swipe to the next slide in the console everything working fine! no clicks by swiping!

if you click on any slide a opening store… message it is showing in the console! this is OK

but if you click over the clickable heart at the top left or right side of the slide, a swiper click is propagated showing opening store… message again. that is not correct!

if you refresh the page by pulling down it will simulate the load of new stores or no stores I just created a random array here, when you do that, the slide content change, the images stay the same as before, the swipe.update() seems not to load properly the images and next slide is not loaded.

if I reinit the swiper slides after update because swiper.update() seems not to update properly the images, or destroy and recreate it again then when swiping to the next slide, a click start propagating again with every swipe “opening store…” message shows by swiping! this is not correct too.!

I just want to swipe when swipe and when click, to click and fire only that action! and when updating slide content update not only the content but also load correctly the images including the next slide…

any chances to do this now with the framework7 last update? before it was working fine!

here the sample code!

<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="left"><a href="#" class="link back"><i class="icon icon-back"></i><span class="if-not-md">Back</span></a></div>
        <div class="title">Swiper</div>
      </div>
    </div>
    <div class="page-content ptr-content" @ptr:refresh="${refreshStores}">


      <div class="ptr-preloader">
        <div class="preloader"></div>
        <div class="ptr-arrow"></div>
      </div>

      <div data-lazy='{"enabled": true, "loadPrevNext": true, "loadPrevNextAmount": 2, "loadOnTransitionStart": false}' data-observer="true" data-space-between="5" data-slides-per-view="auto" data-loop="false" data-centered-slides="false" class="swiper stores swiper-lazy">
        <div class="swiper-wrapper">

          ${stores ? $h`

            ${stores.length > 0 ? $h`

              ${stores.map((f) => $h`

                <div class="swiper-slide swiper-lazy" data-background="${f.current_url}">
                    <div class="swiper-lazy-preloader"></div>

                    <div class="fab fab-right-top color-pink">
                      <a href="#" @click="${heartRightClicked}">
                        <i class="f7-icons size-32">${f.in_favorite ? $h`heart_circle_fill` : `heart_circle`}</i>
                      </a>
                    </div>

                    <div class="fab fab-left-top color-yellow">
                      <a href="#" @click="${heartLeftClicked}">
                        <i class="f7-icons size-32">${f.in_favorite ? $h`heart_circle_fill` : `heart_circle`}</i>
                      </a>
                    </div>

                    <div class="fab fab-center-center color-white">
                      slide ${f.id}
                    </div>

                </div>
              `)}

            ` : $h`

              <div class="swiper-slide">
                <div class="fab fab-center-center color-black">
                  no stores found! please refresh!...
                </div>
              </div>
            
            `}

          ` : $h`
          
            <div class="swiper-slide skeleton-effect-fade">
                <div class="fab fab-center-center color-black">
                  loading stores...
                </div>
            </div>

          `}

        </div>
      </div>

    </div>
  </div>
</template>
<script>
export default (props, {
    $,
    $f7router,
    $f7,
    $update,
    $on,
    $onBeforeMount,
    $onMounted,
    $onBeforeUpdate,
    $onUpdated,
    $onBeforeUnmount,
    $onUnmounted,
    $store,
  }) => {

  let stores = null;

  const heartRightClicked = (e, done) => {
    console.log('heart right clicked')

  }

  const heartLeftClicked = (e, done) => {
    console.log('heart left clicked')
  }


  const refreshStores = (e, done) => {

    var rndStores = [
      [
        {id: 4, "current_url":"https://swiperjs.com/demos/images/nature-4.jpg",in_favorite: true}, 
        {id: 5, "current_url":"https://swiperjs.com/demos/images/nature-5.jpg",in_favorite: true}, 
      ],
      [
        {id: 2, "current_url":"https://swiperjs.com/demos/images/nature-2.jpg",in_favorite: true}, 
      ],
      [],
      [
        {id: 3, "current_url":"https://swiperjs.com/demos/images/nature-3.jpg",in_favorite: true}, 
        {id: 4,"current_url":"https://swiperjs.com/demos/images/nature-4.jpg",in_favorite: true}, 
        {id: 2,"current_url":"https://swiperjs.com/demos/images/nature-2.jpg",in_favorite: true}, 
      ],
    ];

    var rndStores = rndStores[Math.floor(Math.random()*rndStores.length)];
    console.log({rndStores});

    stores = rndStores;
    $update();
    done();

    var swiperStores = $f7.swiper.get('.swiper.stores');
    swiperStores.slideTo(0,'0');
    swiperStores.update();

  }

  $onMounted((p = $el.value) =>

    setTimeout(() => {

      stores = [
        {id: 1, "current_url":"https://swiperjs.com/demos/images/nature-1.jpg",in_favorite: true}, 
        {id: 2, "current_url":"https://swiperjs.com/demos/images/nature-2.jpg",in_favorite: false},
        {id: 3, "current_url":"https://swiperjs.com/demos/images/nature-3.jpg",in_favorite: true},
        {id: 4, "current_url":"https://swiperjs.com/demos/images/nature-4.jpg",in_favorite: false},
        {id: 5, "current_url":"https://swiperjs.com/demos/images/nature-5.jpg",in_favorite: true},
      ];
      $update();

      setTimeout(() => {

        $f7.swiper.create('.swiper.stores', {
            lazy: {
                checkInView: false,
                loadPrevNext: true,
                loadPrevNextAmount: 3
            },
            observer: true,
            slidesPerView: 'auto',
            spaceBetween: 5,
            centeredSlides: false,
            preventClicks: true,
            preventClicksPropagation: false,
            on: {
              init: function () {
                console.log('swiper init');
              },
              click: function (swiper, e) {
                  e.preventDefault();
                  //this action has not to fire when swiping or when clicking heart left or right
                  console.log('swiper click');
                  console.log('opening store...') 
              },
              tap: function (swiper, e) {
                console.log('swiper tap');
                e.preventDefault();
              },
              touchStart: function (swiper, e){
                console.log('swiper touchStart');
                e.preventDefault();
              },  
              touchMove: function (swiper, e){
                console.log('swiper touchMove');
                e.preventDefault();
              },
              touchEnd: function (swiper, e){
                console.log('swiper touchEnd');
                e.preventDefault();
              },
              observerUpdate: function (swiper, e) {
                console.log('swiper observerUpdate');
              }, 
              afterInit: (swiper) => {
                console.log('swiper afterInit');
              },
              slideChange: () => {
                console.log('swiper slideChange');
              },
            }
        })

      }, 200)


    }, 500)

  );

  return $render; 
};
  
</script>

<style>

.swiper .fab-right-top {
  margin-top: 0px !important;
}

.swiper .fab-left-top {
  margin-top: 0px !important;
}

.color-white {
  color:#fff;
  font-size: 4rem;
}

.color-black {
  color:#000;
  font-size: 2rem;
}

.swiper-lazy{
  width: 100%;
  height: 245px;
  border: 1px solid #cdcdcd;
  background-size: cover;
  border-radius:5px;
}

.swiper-slide {
    width: 95%;
    background-size: cover;
    background-position: center;
    font-weight: 300;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #fff;
    color: #000;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    background-size: cover;
    background-position: center;
}

</style>

here is the initial page OK

if you swipe you will not see in the console any click action while swiping! OK

when you click over a heart left or right it fires the “swiper click” action too together with the heat clicked action and that is incorrect!

If I pull down to refresh the page “@ptr:refresh”, the slide content has changed but the images stay the same as before! also sometimes the next slide is not loaded and stay blank!

these are the issues with the new update I am having!
any solution? any tips or ideas?
thanks

thanks for helping to find out a solution! I put the sample code above!
thanks a lot in advance! deejay!

here => [swiper ptr] romantic-violet-8htn2d - CodeSandbox

1 Like

thanks for the shared code! I have made my test now it seems images are updating correctly this way, I just changed

const store = ....

to

let store = ....

so I can replace the content of the store variable with new or different stores. In my case every refresh means that it calls the api to request new stores, sometimes
the request return 0 stores and sometimes > 0 and are not always the same stores etc…

Here my code again after tests and working fine this way!

I just added too to test it with slidesPerView set to auto and working fine too!

    slidesPerView: 'auto',

and now I am able to see one complete card and part of the second one in the viewport and refresh working ok!

Big thanks for your tips and ideas to make this work!

My code again with the changes!

<template>
  <div class="page">
    <div class="navbar">
      <div class="navbar-bg"></div>
      <div class="navbar-inner sliding">
        <div class="left"><a href="#" class="link back"><i class="icon icon-back"></i><span class="if-not-md">Back</span></a></div>
        <div class="title">Swiper v9 test</div>
      </div>
    </div> 
    <div class="page-content ptr-content" data-ptr-mousewheel="true" @ptr:refresh="${(e,d) => refresh(d)}">
      <div class="ptr-preloader"><div class="preloader"></div><div class="ptr-arrow"></div></div>

      <div class="block">
        <div class="swiper">
          <div class="swiper-wrapper">

        ${stores ? $h`

          ${stores.length > 0 ? $h`

            ${stores.map(i => $h`
            <div key="${i.unique}" class="swiper-slide swiper-lazy" data-background="${i.current_url}?nocache=" @click="${() => i.click() }">
              <div class="fab fab-right-top color-${i.like ? 'red' : 'primary'}">
                <a href="#" @click="${(e) => i.toggle(e.stopPropagation())}"><i class="f7-icons size-32">${i.liked ? $h`heart_circle_fill` : `heart_circle`}</i></a>
              </div>
              <div class="text-white" style="background:#000">${i.title} ${i.liked ? $h`liked` : `no like`}</div>
              <div class="swiper-lazy-preloader"></div>
            </div>
            `)}

          ` : $h`

            <div class="swiper-slide swiper-lazy stores-not-found">
              <div class="text-black">no stores found!, please refresh</div>
            </div>

          `}

        ` : $h`

          <div class="swiper-slide  swiper-lazy stores-loading">
            <div class="text-black">loading... please wait...</div>
          </div>

        `}


          </div>
        </div>

        <div class="swiper-button-next"></div>
        <div class="swiper-button-prev"></div>
  

      </div>
    </div>
  </div>
</template>
<script>
export default (_,{ $el, $f7, $onMounted, $update }) => {

    //const stores = [...Array(10).keys()].map(i => ({ media: `https://swiperjs.com/demos/images/nature-${++i}.jpg` }));
    let stores = null;

    stores = [
          {id: 1, "current_url":"/static/slides/1.jpg",liked: false}, 
          {id: 2, "current_url":"/static/slides/2.jpg",liked: true}, 
          {id: 3, "current_url":"/static/slides/3.jpg",liked: false}, 
          {id: 4, "current_url":"/static/slides/4.jpg",liked: true}, 
          {id: 5, "current_url":"/static/slides/5.jpg",liked: false}
    ]
    $update();

    stores.map((i,x) => Object.assign(i,{
      like: i.liked,
      title: `store ${i.id}`,
      toast: `open store ${x}`,
      unique: $f7.utils.id('slide-xxxxx'),
      toggle: () => [i.like = !i.like, $update()],
      click: () => {
        //$f7.toast.create({ text: i.toast, position: 'center', closeTimeout: 2000 }).open();
        console.log('opening store in a new page...')
      }
    }));



  const refresh = (done) => {

    var rndStores = [
      [
        {id: 5, "current_url":"/static/slides/5.jpg",liked: true}, 
        {id: 4, "current_url":"/static/slides/4.jpg",liked: true}, 
        {id: 3, "current_url":"/static/slides/3.jpg",liked: true}, 
        {id: 2, "current_url":"/static/slides/2.jpg",liked: true}, 
        {id: 1, "current_url":"/static/slides/1.jpg",liked: true}, 
      ],
      [
        {id: 1, "current_url":"/static/slides/1.jpg",liked: false}, 
      ],
      [
        {id: 4, "current_url":"/static/slides/4.jpg",liked: true}, 
        {id: 5, "current_url":"/static/slides/5.jpg",liked: true}, 
      ],
      [
        {id: 2, "current_url":"/static/slides/2.jpg",liked: false}, 
      ],
      [
        {id: 5, "current_url":"/static/slides/5.jpg",liked: false}, 
      ],
      [],
      [
        {id: 3, "current_url":"/static/slides/3.jpg",liked: true}, 
        {id: 2, "current_url":"/static/slides/2.jpg",liked: true}, 
      ],
      [
        {id: 1, "current_url":"/static/slides/1.jpg",liked: false}, 
      ],
      [
        {id: 4, "current_url":"/static/slides/4.jpg",liked: false}, 
      ],
    ];

    var rndStores = rndStores[Math.floor(Math.random()*rndStores.length)];

    stores = rndStores;

    stores.map((i,x) => Object.assign(i,{
      like: i.liked,
      title: `store ${i.id}`,
      toast: `open store ${x}`,
      unique: $f7.utils.id('slide-xxxxx'),
      toggle: () => [i.like = !i.like, $update()],
      click: () => {
        //$f7.toast.create({ text: i.toast, position: 'center', closeTimeout: 2000 }).open();
        console.log('opening store in a new page...')
      }
    }));

    stores.reverse();

    stores.map(i => i.unique = $f7.utils.id('slide-xxxxx'));
    $update().then(done).then(() => {
      let s = $f7.swiper.get($el.value.find('.swiper'));
      s.update();
      s.slideTo(0);
      [...Array(s.params.lazy.loadPrevNextAmount).keys()].forEach(s.lazy.loadInSlide);
    });
  };

  $onMounted((p = $el.value) => 
    Array.from(p.find('.swiper')).map(i => $f7.swiper.create(i,{
      observer: true,
      slidesPerView: 'auto',
      spaceBetween: 5,
      slidesPerView: 'auto',
      watchSlidesProgress: true,
      lazy: {
        loadPrevNext: true,
        loadPrevNextAmount: 3
      },
      pagination: {
        clickable: true,
        el: p.find('.swiper-pagination')
      },
      navigation: {
        nextEl: p.find('.swiper-button-next'),
        prevEl: p.find('.swiper-button-prev'),
      },
      on: {
          init: function (s) {
            console.log('swiper init');
          },
          click: function (swiper, e) {
              console.log('swiper click');
              e.preventDefault();
          },
          tap: function (swiper, e) {
            console.log('swiper tap');
            e.preventDefault();
          },
          touchStart: function (swiper, e){
            console.log('swiper touchStart');
            e.preventDefault();
          },  
          touchMove: function (swiper, e){
            console.log('swiper touchMove');
            e.preventDefault();
          },
          touchEnd: function (swiper, e){
            console.log('swiper touchEnd');
            e.preventDefault();
          },
          observerUpdate: function (swiper, e) {
            console.log('swiper observerUpdate');
          }, 
          afterInit: (swiper) => {
            console.log('swiper afterInit');
          },
          slideChange: () => {
            console.log('swiper slideChange');
          },
        }

    })).forEach(i => p.once('page:beforeremove',() => i.destroy()))
  );
  return $render;
};
</script>

<style>


.swiper-lazy{
  width: 100%;
  height: 245px;
  border: 1px solid #cdcdcd;
  background-size: cover;
  border-radius:5px;
}
.swiper-slide {
    width: 95%;
    background-size: cover;
    background-position: center;
    font-weight: 300;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #fff;
    color: #000;
    -webkit-box-pack: center;
    -ms-flex-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    -webkit-box-align: center;
    -ms-flex-align: center;
    -webkit-align-items: center;
    align-items: center;
    background-size: cover;
    background-position: center;
}

.swiper-slide .text-white {
  color:#fff;
  font-size: 28px;
}

.swiper-slide .text-black {
  color:#000;
  font-size: 28px;
}

.swiper .fab-right-top {
  margin-top: 0px !important;
}

.swiper .fab-left-top {
  margin-top: 0px !important;
}



</style>