vue.jsvuejs3primevue

How to hide PrimeVue carousel navigation buttons and indicators on mobile?


I have a problem trying to hide carousel navigation buttons and indicators on mobile.

I tried to use responsiveOptions for this, but it didn't work. The array of options for responsiveness looks like this:

const responsiveOptions = ref([
  {
    breakpoint: '1200px',
    numVisible: 3,
    numScroll: 1
  },
  {
    breakpoint: '767px',
    numVisible: 2,
    numScroll: 1,
    showNavigators: false
  },
  {
    breakpoint: '475px',
    numVisible: 1,
    numScroll: 1,
    showIndicators: false
  },
])

My carousel component:

<Carousel :value="products" :num-visible="4" :num-scroll="1"
          :responsive-options="responsiveOptions" circular
          :autoplay-interval="3000"
>
<template v-slot:previousicon>
  <span class="material-symbols-sharp">
    chevron_left
  </span>
</template>
<template #item="slotProps">
  <div class="card position-relative product-card h-100">
    <div class="offer position-absolute top-0 left-0 d-flex flex-column p-2">
      <span class="offer-hit mb-2" v-if="slotProps.data.hit">Hit</span>
      <span class="offer-new" v-if="slotProps.data.new">New</span>
    </div>
    <img :src="slotProps.data.image" class="card-img-top" alt="">
    <div class="card-body">
      <h5 class="card-title"><strong>{{ slotProps.data.title }}</strong></h5>
      <p class="card-text">{{ slotProps.data.description }}</p>
    </div>
    <div class="card-footer d-flex justify-content-between align-items-center">
      <h5 class="card-title m-0">
        <s><small>{{ slotProps.data.oldPrice }}$</small></s>
        {{ slotProps.data.price }}$
      </h5>
      <button class="btn btn-danger p-1">
        <span class="material-symbols-sharp" style="vertical-align: bottom;">
          shopping_cart
        </span>
      </button>
    </div>
  </div>
</template>
<template v-slot:nexticon>
  <span class="material-symbols-sharp">
    chevron_right
  </span>
</template>
</Carousel>

I know I can use CSS to do this, but I want to find out if there are any in-built options/methods I could use to achieve the desired result.

If you need something else to understand my question, feel free to ask.


Solution

  • One way to do this is to create a Vue composable if you are concerned about reusing this code.

    export const useMediaQuery = () => {
      const isMobile = ref(null)
      const mql = ref(null)
    
      function update(e) {
        isMobile.value = e.matches
      }
    
      onMounted(() => {
        mql.value = window.matchMedia('(max-width: 1024px)')
        isMobile.value = window.matchMedia('(max-width: 1024px)').matches
        mql.value.addEventListener('change', update)
      })
    
      onUnmounted(() => {
        mql.value.removeEventListener('change', update)
      })
    
      return { isMobile }
    }
    

    Then you could use this in your component.

    <script setup>
    import { useMediaQuery } from './useMediaQuery.js'
    
    const { isMobile } = useMediaQuery()
    </script>
    
    <template>
      <Carousel :showIndicators="isMobile ? false : true"/>
    </template>