What could be causing the issue with the navigation circles on my carousel not updating when clicked?

I created my own carousel from scratch and it's working perfectly fine except for one issue - clicking on the navigation circles. When using the interval/infinite loop prop, the circles update to the correct active slide as expected. The same goes for pressing the side left and right buttons. However, when trying to click directly on the circles, things go haywire and the carousel breaks. It seems to be related to the switchSlide function I wrote for that action, but I'm struggling to figure it out.

Any help or suggestions would be greatly appreciated!

Cheers!

You can find the Codesandbox here

NOTE: I only added the index inside each circle to ensure the proper amount were rendering.

Carousel.vue

<template>
  <div class="audition-hero-carousel">
    <div class="carousel-inner">
      <div v-if="navigation" class="carousel-circles">
        <button
          v-for="(fileInfo, index) in modelValue"
          class="carousel-circle-item"
          :style="{ background: `${color}` }"
          :class="{ active: currentSlide === index }"
          :key="index"
          :name="index"
          @click="(index) => switchSlide(index)"
        ></button>
      </div>
      <TransitionGroup :name="transitionEffect">
        <div
          v-show="currentSlide === index"
          v-for="(fileInfo, index) in modelValue"
          :key="index"
          :name="index"
          class="carousel-item"
          @mouseenter="() => stopSlideTimer()"
          @mouseout="() => startSlideTimer()"
        >
          <img
            v-if="fileInfo.type.startsWith('image')"
            :src="fileInfo.url"
            class="_img"
            draggable="false"
          />
        </div>
      </TransitionGroup>
      <div v-if="controls">
        <button
          :style="{ color: `${color}` }"
          class="carousel-control left"
          @click="() => prev()"
        >
          ←
        </button>
        <button
          :style="{ color: `${color}` }"
          class="carousel-control right"
          @click="() => next()"
        >
          →
        </button>
      </div>
    </div>
  </div>
  <!-- {{modelValue}} -->
</template>

<script>
export default {
  name: "CAuditionHeroCarousel2",
  props: {
    /**
     * @type {{ type: 'image' | 'video' | 'youtube', url: string }[]}
     */
    modelValue: { type: Array },
    controls: {
      type: Boolean,
      default: false,
    },
    navigation: {
      type: Boolean,
      default: false,
    },
    interval: {
      type: Number,
      default: 5000,
    },
    infinite: {
      type: Boolean,
      default: true,
    },
    color: {
      type: String,
      default: "#9759ff",
    },
  },
  data() {
    return {
      currentSlide: 0,
      direction: "right",
    };
  },
  methods: {
    setCurrentSlide(index) {
      this.currentSlide = index;
    },
    prev(step = -1) {
      const index =
        this.currentSlide > 0
          ? this.currentSlide + step
          : this.modelValue.length - 1;
      this.setCurrentSlide(index);
      this.direction = "left";
      this.startSlideTimer();
    },
    _next(step = 1) {
      const index =
        this.currentSlide < this.modelValue.length - 1
          ? this.currentSlide + step
          : 0;
      this.setCurrentSlide(index);
      this.direction = "right";
    },
    next(step = 1) {
      this._next(step);
      this.startSlideTimer();
    },
    startSlideTimer() {
      if (this.infinite) {
        this.stopSlideTimer();
        setInterval(() => {
          this._next();
        }, this.interval);
      }
    },
    stopSlideTimer() {
      clearInterval(this.interval);
    },
    switchSlide(index) {
      const step = index - this.currentSlide;
      if (step > 0) {
        this.next(step);
      } else {
        this.prev(step);
      }
    },
  },
  computed: {
    transitionEffect() {
      return this.direction === "right" ? "slide-out" : "slide-in";
    },
  },
  mounted() {
    if (this.infinite) {
      this.startSlideTimer();
    }
  },
  beforeUnmount() {
    this.stopSlideTimer();
  },
};
</script>

<style lang="sass" scoped>
// Carousel Main
.audition-hero-carousel
  display: flex
  justify-content: center
  min-width: 0px
  width: 450px
  height: 200px

.carousel-inner
  position: relative
  width: 100%
  height: 100%
  overflow: hidden

.carousel-circles
  position: absolute
  display: flex
  justify-content: center
  transform: translateX(-50%)
  left: 50%
  bottom: 2em
  width: 100%
  z-index: 2

.carousel-circle-item
  width: 15px
  height: 15px
  border: none
  opacity: 0.65
  margin-right: 20px
  border-radius: 50%
  cursor: pointer
  &:hover
    cursor: pointer

  &:last-child
    margin-right: 0px

._img,
._video
  width: 100%
  height: 100%
._img
  object-fit: cover
._video > *
  height: 100%
  width: 100%

.active
  opacity: 1

/**
 Carousel Item styles
 */
.carousel-item
  position: absolute
  top: 0
  left: 0
  right: 0
  bottom: 0

.slide-in-enter-active,
.slide-in-leave-active,
.slide-out-enter-active,
.slide-out-leave-active
  transition: all 300ms ease-in-out

.slide-in-enter-from
  transform: translateX(-100%)

.slide-in-leave-to
  transform: translateX(100%)

.slide-out-enter-from
  transform: translateX(100%)

.slide-out-leave-to
  transform: translateX(-100%)

/**
 Controls
 */
.carousel-control
  outline: none
  border: none
  background: transparent
  display: inline-block
  position: absolute
  height: 50px
  width: 70px
  top: calc(50% - 20px)
  cursor: pointer

.left
  left: 0

.right
  right: 0
</style>

App.vue

<template>
  <Carousel
    :modelValue="slides"
    :interval="3000"
    :navigation="true"
    :controls="true"
    :infinite="false"
    :color="'#fff'"
  />
</template>

<script>
import Carousel from "./components/Carousel.vue";
export default {
  name: "App",
  components: {
    Carousel,
  },
  data() {
    return {
      slides: [
        { type: "image", url: "https://picsum.photos/id/1032/900/400" },
        { type: "image", url: "https://picsum.photos/id/1033/900/400" },
        { type: "image", url: "https://picsum.photos/id/1037/900/400" },
        { type: "image", url: "https://picsum.photos/id/1035/900/400" },
        { type: "image", url: "https://picsum.photos/id/1036/900/400" },
      ],
    };
  },
};
</script>

Answer №1

Consider updating the method call like this:

@click="switchSlide(index)"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Generating images using Node.js and GraphicsMagick

I'm looking for a way to generate an image using graphicsMagick and node.js. Typically, I can achieve this with the following command: gm convert -background transparent -pointsize 30 -gravity Center label:türkçee HEEEEEY.png But I need to replic ...

Bundling and minifying Angular2 assets

In the world of ASP.NET (or gulp), bundling and minification are taken care of. However, a different issue arises when following Angular2 tutorials: the view HTML is typically embedded within the component itself. Fortunately, there is a way to separate th ...

Display requested tab feature using jQuery upon page load

I am new to jquery and have been using this code for creating tabs: <script type="text/javascript" charset="utf-8> $(function () { var tabContainers = $('div.tabs > div'); tabContainers.hide().filter(':first&apo ...

5 Creative Techniques for Manipulating Boolean Variables in If Statements

I am receiving a unique custom header value and the values I am getting are accurate. The expected values include: true, false, undefined. However, the response associated with the value: false is incorrect. Code Snippet let deviceStatus = req.headers[ ...

Utilizing one JavaScript file and consistent classes for multiple modals

Is it possible to have multiple modals using the same JS file, classes, and IDs? I created this code: <button id='myBtn'>Order/Discount</button> <div id='myModal' class='modal'> <div clas ...

"Customizable rectangular container with jagged edges created with Scalable Vector Graphics

Currently, I am undertaking a small project that involves creating a box with rough edges around some text. To achieve this effect, I am utilizing an SVG with unique edges similar to the design found at this link: (except mine is in SVG format). My goal ...

When I select an option with an object, ng-model is receiving '[object Object]' instead of the actual object for <select> element

Referencing an example from Angular documentation: this link, specifically the section on "Using ngValue to bind the model to an array of objects." In the index.html file: <!doctype html> <html lang="en"> <head> <meta charset="UTF- ...

Pass data from controller using Ajax in CodeIgniter

Here is my JavaScript code: $(document).ready(function(){ $("input[type='checkbox']").change(function(){ var menu_id = this.value; if(this.checked) var statusvalue = "On"; else var statusvalue = "Off"; $.ajax( ...

The type {properties .....} is incompatible with the type ActionReducer<AdminState, Action> in Angular 12 using NGRX

Implementing NGRX library for redux to organize the state of the application in a structured way: export interface ApplicationState { adminState: AdminState } export interface AdminState { adminProductCategory: ProductCategoryState; adminProdu ...

Establish a predetermined selection for a drop-down menu

How can I set a default value for a dynamically filled dropdown menu featuring all 12 months in KnockoutJS? I want the default value to be the current month. This is how I am populating the dropdown with information: self.setMonthData = (data ...

Discover the best method for transferring MySQL data between pages

Can anyone help guide me in the right direction on how to allow a user to click a link within a PHP While Loop generated MySQL table and pass that data to another page? I've searched through similar questions but haven't found a solution that fit ...

What is the method for incorporating choices into a schema field in Mongoose?

If my Schema is like this: var fooSchema = new Schema({ foo: String }); and I'm looking to implement select: false for foo, how can I achieve this without altering the initial structure? var fooSchema = new Schema({ foo: { type: String, select: ...

Tips for concealing a particular button that shares the same class designation

Is there a way to create a function in vanilla JavaScript that can hide a specific button? <button class"btn">button 1 </button> <button class"btn">button 2 </button> <button class"btn">button 3 </button> Specifically, ...

Guide on establishing two loops in React JS

I'm receiving a JSON array that contains nested arrays. I attempted to iterate through it using two loops, but so far, I haven't been successful. {this.state.listOfAlarms && this.state.listOfAlarms.map((alarms) => {alarms.repo ...

When using Node Puppeteer, if the page.on( "request" ) event is triggered, it will throw an error message stating "Request is already being handled!"

I am currently utilizing puppeteer-extra in conjunction with node.js to navigate through multiple URLs. During each iteration, I am attempting to intercept certain types of resources to load and encountering the error below. PS C:\Users\someuser ...

Did the IBM MobileFirst client miss the call to handleFailure?

I am currently utilizing the IBM MFP Web SDK along with the provided code snippet to send challenges and manage responses from the IBM MobileFirst server. Everything functions properly when the server is up and running. However, I have encountered an iss ...

angularjs issue with $setPrestine function not providing reliable results

I have encountered an issue with the login form code. Initially, I am able to reset the form fields and error messages successfully on the first attempt (both success and failure scenarios work). However, on the second try, I am unable to reset the form fi ...

Does the webworker function as a multi-thread?

For example: worker.postMessage(data1); worker.postMessage(data2); If there are multiple issues to be dealt with inside the web worker, would worker.postMessage(data2) block before completing data1? ...

Retrieve Header information when making a cross-domain AJAX request

I've been working on a way to validate image URLs by using an AJAX call to check if the image is still available. The challenge I'm facing is that the image server is on a different domain, so I included the crossDomain: true attribute in my AJAX ...

Is there a way to delete a stylesheet if I only have limited information about the url?

I am attempting to dynamically remove a CSS stylesheet using JavaScript or jQuery. I am aware that the target stylesheet is located within the 'head' element and includes the text 'civicrm.css', however, I do not possess the full URL o ...