swiper js slides malfunction

swiper js malfunction when updating number of slides dynamically

by Glow_Jr

HTML

<div id="demo">
  <div class="text-center">
    <v-btn-toggle v-model="selectedMedia"
                  mandatory active-class="selectedMedia" dense >
      <v-btn :value="null">
        <span>All</span>
      </v-btn>
      <v-btn v-for="media in listAllMedia" :value="media.code" :key="media.code">
        <span>{{media.label}}</span>
      </v-btn>
    </v-btn-toggle>
  </div>

  <swiper-container ref="swiper" :slides-per-view="isMobile ? 2 : 10"
                    :space-between="isMobile ? 5 : 10"
                    :centered-slides="false"
                    :scrollbar="true" 
                    :scrollbar-draggable="true" 
                    :scrollbar-drag-size="isMobile ? 50 : 100" 
                    :free-mode="true"
                    
                    breakpoints='{"100": {"slidesPerView": 2}, "480": {"slidesPerView": 3}, "650": {"slidesPerView": 4}, "850": {"slidesPerView": 5}, "950": {"slidesPerView": 6}, "1150": {"slidesPerView": 7}, "1300": {"slidesPerView": 8}, "1500": {"slidesPerView": 9}, "1700": {"slidesPerView": 10}}'>

     <template v-for="(chara, index) in filteredListCharacters">
      
        <v-card :slot="'slide-' + index" style="height: 300px; border: 1px solid black">

          <v-card-title style="color: black; padding-top: 10px;">{{chara.name}}
          </v-card-title>

          <v-card-text style="padding-top: 5px; padding-bottom: 5px;">
            <div v-for="media in chara.medias" style="font-style: italic; color: gray; font-size: 10px;">{{listAllMedia.filter(x => x.code == media)[0]?.label}}</div>
          </v-card-text>
        </v-card>     
    </template>  
  </swiper-container>
</div>                                            
                                               
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2/dist/vuetify.js"></script>
<script...

JavaScript

var demoApp = new Vue({
    el: '#demo',    
    data: {
            selectedMedia: null,
            listAllMedia: [
            	{ code: "med1", label: "Media 1" },
              { code: "med2", label: "Media 2" },
            	{ code: "med3", label: "Media 3" },
              { code: "med4", label: "Media 4" },
              { code: "med5", label: "Media 5" },
              { code: "med6", label: "Media 6" },
              { code: "med7", label: "Media 7" },
              { code: "med8", label: "Media 8" },
        ],
        isMobile: false,
        characters: [
          { name: "A", medias:["med1", "med2", "med3"] },
          { name: "B", medias:["med2", "med4", "med8"] },
          { name: "C", medias:["med1", "med2", "med3"] },
          { name: "D", medias:["med1", "med8", "med6"] },
          { name: "E", medias:["med8", "med5", "med7"] },
					{ name: "F", medias:["med1", "med6", "med5"] },
          { name: "G", medias:["med7", "med4", "med3"] },
          { name: "H", medias:["med1", "med3", "med6"] },
          { name: "I", medias:["med5", "med6", "med8"] },
        ]
    },
    computed: {
        filteredListCharacters: function () {
            var self = this;
            var result = self.selectedMedia == null ? self.characters : self.characters.filter(x => x.medias?.includes(self.selectedMedia))
            
						//what's bellow didn't work
            //const swiperEl = document.querySelector('swiper-container');
            //if (swiperEl != null) {                
            //    swiperEl.swiper.update();
            //}
            return result;
        }
    },
});

//didn't work
//function onWindowSize() {
//    const swiperEl = document.querySelector('swiper-container');
//    if (swiperEl != null) {
//        console.log("update")
//        swiperEl.swiper.update();

//    }
//}

//window.onresize = onWindowSize;