# Slide counter for carousel?

**URL:** <https://forum.builder.io/t/slide-counter-for-carousel/1445>\
**Category:** Technical Questions\
**Created:** [December 9, 2021, 10:33pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445 "2021-12-09T22:33:37Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 9, 2021, 10:33pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/1 "2021-12-09T22:33:37Z")

</div>

We would like to add a counter to our Builder carousel component, to show the user they are on Slide X of Y. Is this possible? Could it be done with some custom javascript?

---

<div class="post-metadata">

**Author:** ![TimG](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.builder.io/timg/32/714_2.png) [@TimG](https://forum.builder.io/u/TimG)\
**Post date:** [December 9, 2021, 10:39pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/2 "2021-12-09T22:39:05Z")

</div>

@Canuckaholic definitely, this shouldn’t be too complicated, and there are many ways you could do it. You could create your own [custom component](https://www.builder.io/c/docs/custom-react-components) that includes this logic, or if you wanted to still use the Builder component you could just add some custom JS in the Custom JS + CSS window:

> **[Adding custom code in the Builder.io visual editor - Builder.io](https://www.builder.io/c/docs/guides/custom-code)**
>
> Add custom JavaScript and CSS to your Builder content. Learn how to access browser events, state properties and add custom CSS to your pages.

Hopefully that gives you a few directions you could go…Take a look and try it out and let us know if you have any follow up questions!

---

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 9, 2021, 10:53pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/3 "2021-12-09T22:53:00Z")

</div>

Thanks for the quick reply! We are on the same page in that I am looking to add some custom JS in the Custom JS + CSS window, however the trick is going to be determining how many slides have been added to the carousel in order to show the user they are on slide 5 / 7, for example. So my custom JS code is going to need some information from the carousel in order to display the right numbers.

---

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 9, 2021, 11:14pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/4 "2021-12-09T23:14:51Z")

</div>

One idea I have is to use the Content API, fetch my symbols (my carousel is in a symbol), and then count the number of slides in the JSON result for the carousel object.

Is there a way to use the Content API (ie. do a fetch) directly from inside Builder?

---

<div class="post-metadata">

**Author:** ![TimG](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.builder.io/timg/32/714_2.png) [@TimG](https://forum.builder.io/u/TimG)\
**Post date:** [December 9, 2021, 11:54pm UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/5 "2021-12-09T23:54:38Z")

</div>

@Canuckaholic that would work. You could hit the Content API in a fetch() within the JS+CSS window

```auto
    await fetch(someUrl)
      .then(res => res.json())
      .then(data => {
        // set the data on the state object so you can access it from your components
        state.someData = data;
     });

```

or add it as an API call in the +API Data section, but I think the most straight forward way could be to just add a class name to each carousel slide in the CSS Class section of the Style tab

![Screen Shot 2021-12-09 at 2.57.23 PM](https://us1.discourse-cdn.com/flex020/uploads/builder/original/1X/c03833368a4e90351dd51f9d3db50a179213b068.png)

and then you can grab the items using `document.getElementsByClassName(className).length` and use that to figure out the length and where you are within the carousel, etc.

Let me know if that works for you!

---

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 10, 2021, 12:52am UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/6 "2021-12-10T00:52:00Z")

</div>

I have the following code almost working. What I did is add my Carousel symbol as a data source for itself using the “Connect data from popular sources” section. It works if I edit the JS, close the edit window, and see the UI respond. However, I’m noticing that `state.symbol` is undefined on page load, so it doesn’t actually work.

```auto
    var blocks = state.symbol?.data?.blocks
    if (blocks?.length) {
      var carousel = blocks.find(block => {
        return block.component?.name === 'Builder:Carousel'
      })

      var currentSlide = 1
      var totalSlides = carousel.component.options.slides.length
      var counterEl = document.getElementById('counter')
      counterEl.textContent = currentSlide + " / " + totalSlides

      function incrementCount() {
        currentSlide++
        if (currentSlide > totalSlides) {
          currentSlide = 1
        }
        counterEl.textContent = currentSlide + " / " + totalSlides
      }

      function decrementCount() {
        currentSlide--
        if (currentSlide < 1) {
          currentSlide = totalSlides
        }
        counterEl.textContent = currentSlide + " / " + totalSlides
      }

      var nextBtn = document.getElementById('next')
      nextBtn.addEventListener('click', incrementCount)

      var prevBtn = document.getElementById('prev')
      prevBtn.addEventListener('click', decrementCount)
    }
  }

```

---

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 10, 2021, 1:09am UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/7 "2021-12-10T01:09:10Z")

</div>

I have the following in my JS, but on page load it’s not finding the elements in the DOM:

```auto
if (Builder.isBrowser) {

    function getSlidesByClassName() {
      return document.getElementsByClassName('slide').length
    }

    var totalSlides = getSlidesByClassName()
}

```

totalSlides is undefined when the page first loads. Could something be off with the part that waits for the DOM to be loaded before running the JS?

---

<div class="post-metadata">

**Author:** ![Canuckaholic](https://avatars.discourse-cdn.com/v4/letter/c/3e96dc/32.png) [@Canuckaholic](https://forum.builder.io/u/Canuckaholic)\
**Post date:** [December 10, 2021, 1:39am UTC](https://forum.builder.io/t/slide-counter-for-carousel/1445/8 "2021-12-10T01:39:28Z")

</div>

Well for anyone wanting to do this who stumbles upon this thread, here’s my current code that seems to work. It’s not the best implementation though, I would say, so perhaps Builder could add this feature for the carousel to their roadmap?

```auto
    await fetch('https://cdn.builder.io/api/v2/content/symbol?apiKey=<API_KEY>&query.id=<COMPONENT_ID>&limit=1')
      .then(res => res.json())
      .then(data => {
        // set the data on the state object so you can access it from your components
        state.carousel = data.results
    })

   // In case the fetch doesn't work, we can try to get the total from the class names
    function getSlidesByClassName() {
      return document.getElementsByClassName('slide').length
    }

    var totalSlides = getSlidesByClassName()
    var currentSlide = 1
    var wait = false

    var blocks = state.carousel?.[0].data?.blocks || state.symbol?.data?.blocks
    if (blocks?.length) {
      var carousel = blocks.find(block => {
        return block.component?.name === 'Builder:Carousel'
      })
      if (carousel.component.options.slides.length) {
        totalSlides = carousel.component.options.slides.length
      }
    }
    
    var counterEl = document.getElementById('counter')
    counterEl.textContent = currentSlide + " / " + totalSlides

    function startTimer() {
      wait = true
      setTimeout(() => wait = false, 700)
    }

    function incrementCount() {
      if (!wait) {
        startTimer()
        currentSlide++
        if (currentSlide > totalSlides) {
          currentSlide = 1
        }
        counterEl.textContent = currentSlide + " / " + totalSlides
      }
    }

    function decrementCount() {
      if (!wait) {
        startTimer()
        currentSlide--
        if (currentSlide < 1) {
          currentSlide = totalSlides
        }
        counterEl.textContent = currentSlide + " / " + totalSlides
      }
    }

    var nextBtn = document.getElementById('next')
    nextBtn.addEventListener('click', incrementCount)

    var prevBtn = document.getElementById('prev')
    prevBtn.addEventListener('click', decrementCount)

```
