Home > database >  Create kind of carousel Vue
Create kind of carousel Vue

Time:01-16

So, I have a dashboard where I want to display some cards. There should only be four visible at a time and when clicking on the arrow you just want to move one step to the next card. So let's say cards 1-4 are showing and when clicking the right arrow you should be able to see 2-5. Right now I only have that when you click the right arrow you jump pass 1-4 and go straight to 5-10.

So right now I have this:

computed: {
    cardsToDisplay(): Status[] {
        return this.cards.slice(this.page * 4, (this.page   1) * 4)
    },
},
methods: {
    setCards(no: number) {
        this.page = this.page   delta
    },
},

And in the template the left and right arrow buttons look like this:

        <v-icon v-if="page !=="  
          @click="setPage(-1)">
          chevron_left</v-icon>

        <v-icon
            v-if="columns.length > (page   1) * 4"
            
            @click="setPage(1)"
            >chevron_right</v-icon
        >

But how can I make it just move to the next card? :)

CodePudding user response:

Just do

computed: {
    cardsToDisplay(): Status[] {
        return [...this.cards, ...this.cards].slice(this.cards_pos, this.cards_pos   4)
    },
},
methods: {
    prev() {
        this.cards_pos = (this.cards_pos   this.cards.length - 1) % this.cards.length;
    },
    next() {
        this.cards_pos = (this.cards_pos   1) % this.cards.length;
    },
},

With [...this.cards, ...this.cards] you ensure that the carousel is cyclic without much code.
With the remainder operator you ensure your card_pos is always less than the number of cards. With decrementing, you need to add the array length, to prevent going into the negatives.

Vue.createApp({
  data: () => ({
    cards_pos: 0,
    cards: new Array(10).fill(null).map((e, i) => ({
      img: "https://picsum.photos/id/"   (i * 10)   "/200",
      text: "Card #"   (i   1)
    }))
  }),
  computed: {
    cardsToDisplay() {
      return [...this.cards, ...this.cards].slice(this.cards_pos, this.cards_pos   4)
    },
  },
  methods: {
    prev() {
      this.cards_pos = (this.cards_pos   this.cards.length - 1) % this.cards.length;
    },
    next() {
      this.cards_pos = (this.cards_pos   1) % this.cards.length;
    },
  },
}).mount("#app")
.cards {
  display: flex;
  list-style: none;
  padding: 0;
  margin: 0;
  width: 100%;
}

.cards > * {
  width: 25%;
}

.cards > * img {
  width: 100%;
}
<script src="https://unpkg.com/vue@next"></script>
<div id="app">
  <button @click="prev">
    &lt;&lt;
  </button>
  <button @click="next">
    &gt;&gt;
  </button>
  <ol >
    <li v-for="card in cardsToDisplay">
      <img :src="card.img" />
      <p>
        {{ card.text }}
      </p>
    </li>
  </ol>
</div>

  •  Tags:  
  • Related