Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mikromike's avatar

Vue3, composite api, script setup, how to v-for data from script side?

Hello again.

simple first vue3 SFC component is up and running.

https://laracasts.com/discuss/channels/vue/vue3-composite-api-script-setup-loopsettimeout-does-not-work-than-one-index-forward

Next problem is update ref from v-for loop. :ref="banner".

    <div v-for="banner, index in banners.banners"  v-bind:key="banner.id" 
   :iscurrent="currentBanner  ===   index">    
  <div v-show="currentBanner === index">      
    <p> {{ banner.inteval  }}</p>

in script side:

 let banner = ref([]);

I try to reach data banner.inteval and update :

const startBanner = () => {
   clearTimeout(interval.value);  
   interval.value = setTimeout(changeBanner, 30000);    <-  banner.inteval insted hard code.
};

i tried this link: https://borstch.com/blog/development/advanced-usage-of-refs-in-vuejs-3

did not work for me.

thanks Mika.

0 likes
11 replies
LaryAI's avatar
Level 58

Hello Mika,

To access the interval value for each banner within your startBanner function, you need to know which banner's interval you're referring to. Since startBanner seems to be a function that starts the interval for a specific banner, you should pass the current banner's index or the banner object itself to the function.

Here's how you can modify your code to achieve this:

<template>
  <div v-for="banner, index in banners" :key="banner.id" :iscurrent="currentBanner === index">
    <div v-show="currentBanner === index">
      <p> {{ banner.interval }}</p>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';

// Assuming banners is an array of objects and each object has an 'interval' property
const banners = ref([
  // ... your banner objects here
]);

const currentBanner = ref(0);
const interval = ref(null);

const startBanner = (banner) => {
  clearTimeout(interval.value);
  interval.value = setTimeout(() => {
    changeBanner();
    // Do something with banner.interval here
  }, banner.interval);
};

// You would need to define your changeBanner function here
const changeBanner = () => {
  // Logic to change the banner
};
</script>

In the above code, I've made the following changes:

  1. I've assumed banners is an array of objects where each object has an interval property.
  2. The startBanner function now takes a banner parameter, which is the banner object you want to start the interval for.
  3. When setting the timeout, I've used banner.interval to dynamically set the interval duration based on the banner's interval value.

Make sure to call startBanner with the correct banner object when you want to start the interval. For example, you might call it when a banner is clicked or when the component is mounted, depending on your use case.

Remember to define your changeBanner function to handle the logic for changing the banner when the timeout completes.

gych's avatar

Where is the data for the banner interval coming from ? Are you trying to use different timeout durations for each banner ?

mikromike's avatar

@gych,

 async function getBanners()  { try {
        const response =  await axios.post("http://clientdomain.fi/mainos", bannerData);
        banners.value = response.data;
        getBannersCount.value = response.data.banners.length;      
        console.log( response.data.banners);  
        startBanner();

it is banners = ref([]);

 <div v-for="banner, index in banners.banners"  >

I can not pass one banner data: to script setup area, it only works in html side.

banner.inteval is same as

const startBanner = () => { console.log(banner.value.target); clearTimeout(interval.value); interval.value = setTimeout(changeBanner, 30000); <- i want change this dynamic. };

I cannot pass single banner data to startBanner() function. Because is it not available after received data from backend ( Laravel.)

mikromike's avatar

@gych

     const changeBanner = () => {
      if(currentBanner.value === getBannersCount.value -1){ 
       currentBanner.value = 0;     
    } else {
     currentBanner.value += 1;         
   }    
   console.log(currentBanner.value, 'nextBanner after update: currentBanner.value');  
   startBanner();
  };
gych's avatar
gych
Best Answer
Level 29

@mikromike

currentBanner.value holds the index of the current banner. Use that index to get the interval for the current banner from banners.value.banners

See this example

const startBanner = () => {
   clearTimeout(interval.value);  
   const bannerInterval = banners.value.banners[currentBanner.value]['inteval'];
   interval.value = setTimeout(changeBanner, bannerInterval);     
};
1 like
gych's avatar

In the code example above I used inteval as parameter because your banner data has a typo

   0	Object { id: 1, customer_id: 26, alt_text: "domain",inteval	300000 … }

It should be interval and not inteval

mikromike's avatar

@gych I know typo in my backend. it works finally, If you will come visit in Finland, I will buy you bear ,-D

mikromike's avatar
            0	Object { id: 1, customer_id: 26, alt_text: "domain",inteval	300000 … }

yes, interval can change from laravel backend ui tool. that's why it part of response.

mikromike's avatar
  <div v-for="banner, index in banners.banners"  v-bind:key="banner.id" :iscurrent="currentBanner === index"
    v-bind:bannerTimer ="banner.inteval"> 

 const bannerTimer = ref(0);

gives me number 300000 ms which is same as banner.inteval. but if I put variable inside function: my banner going crazy ,-D

    const startBanner = () => {

   clearTimeout(interval.value);
       //interval.value = setTimeout(changeBanner, bannerTimer);    <----- 
  interval.value = setTimeout(changeBanner, 30000);
    console.log(bannerTimer);
   };

Please or to participate in this conversation.