Button in repeater fires several times

I have a button on my repeater on every line ítem! Everything works fine on my page! I have several dropdowns which allow to filter the data in the repeater. Each time a filter is used, the repeater reloads the data! The only issue is that when I apply one or more filters, the button once clicked will fire several times, containing all the data which were stored in the line ítem after the first load, second reload, third reload…This makes little sense to me! I used button.disable + button.enable or button.show + button.hide, nothing really works. Clearing the repeater works but then my repeater + filter disappear until new data are loaded, not really practically either. Also here repeater.show did not help!

I also tried to move the onclick function outside the applyfilter function but this did not work
either.

When your button is linked to a different website, it is not a problem because it will always use the last click to go the right website. But when you have a backend request, this is creating a lot of unnecessary noise!

I have now added a debouncing function which kind of works as a workaround. I am looking for a smoother solution though. Any ideas will be highly appreciated! Below the Code snipplet! Many Many thanks upfront!

$w.onReady(function () {
console.log(“Page ready”);

let repeaterData = []; // Declare this at the top to make it accessible globally within the page
const dob = "2004-12-31"; // Date of birth

// Function to run the query and apply filters
function applyFilters() {
    const selectedOption1 = $w('#dropdown1').value; // Activity
    const selectedAgeRange = $w('#dropdown3').value; // Age Range
    const selectedMonth = $w('#dropdown4').value; // Month
    const selectedBudget = $w('#dropdown5').value; // Budget
    const selectedDuration = $w('#dropdown6').value; // 


let query = wixData.query(“Reservations/bookings”)
.eq(“center_variation_name”, “Lanzarote”);

    if (selectedOption1) {
        query = query.eq("activity_variation_name", selectedOption1);
    }

    if (selectedAgeRange) {
        query = query.ge("product_age_min", minAge).le("product_age_max", maxAge);
    }
    
    //$w("#repeater1").data = []; clearing the repeater 
    //console.log("Repeater data cleared before applying filters.");

    query.find()
        .then(results => {
             
            repeaterData = results.items.map((item, index) => {
                const startDate = new Date(item.date * 1000);
                const endDate = addDays(startDate, item.duration);
                return {
                    _id: index.toString(),
                    startDate,
                    endDate,
                    date: startDate.toLocaleDateString('en-GB'),
                    end: endDate.toLocaleDateString('en-GB'),
                    price: item.price ? item.price
                };
            });

            // Apply month filter
            if (selectedMonth) {
                repeaterData = repeaterData.filter(item => {
                    const itemStartMonth = item.startDate.getMonth() + 1; // Get the month (0-based, so add 1)
                    const itemEndMonth = item.endDate.getMonth() + 1; // Get the month for endDate

                    // Check if the selected month is within the range of start and end dates
                    return (
                        (itemStartMonth === parseInt(selectedMonth, 10)) || 
                        (itemEndMonth === parseInt(selectedMonth, 10)) ||
                        (itemStartMonth <= parseInt(selectedMonth, 10) && itemEndMonth >= parseInt(selectedMonth, 10))
                    );
                });
            }

            // Apply budget filter
            if (selectedBudget) {
                repeaterData = repeaterData.filter(item => item.price <= parseInt(selectedBudget, 10));
            }

            // Apply duration filter
            if (selectedDuration) {
                let minDuration, maxDuration;
                switch (selectedDuration) {
                    case "1-4":
                        minDuration = 1;
                        maxDuration = 4;
                        break;
                    case "5-8":
                        minDuration = 5;
                        maxDuration = 8;
                        break;
                    case "9-30":
                        minDuration = 9;
                        maxDuration = 30;
                        break;
                    default:
                        minDuration = 0;
                        maxDuration = 100;
                }

                repeaterData = repeaterData.filter(item => item.duration >= minDuration && item.duration <= maxDuration);
            }

            // Sort by start date before populating the repeater
            repeaterData.sort((a, b) => a.startDate - b.startDate);

            if (repeaterData.length > 0) {
                $w("#repeater1").data = repeaterData;
                $w("#text128").text = "";
            } else {
                $w("#repeater1").data = [{}];
                $w("#text128").text = "Leider ist schon alles ausverkauft.";
            }

            $w("#repeater1").onItemReady(($item, itemData) => {
                if (itemData._id) {
                    $item("#text123").text = `${itemData.date} - ${itemData.end}`;
                    $item("#text124").text = itemData.availability;
                    $item("#text125").text = `${itemData.price}€`;
                    $item("#text120").text = `Alter: ${itemData.minAge} - ${itemData.maxAge}`;
                    $item("#text121").text = itemData.center;
                    $item("#text122").text = itemData.activity;
                    const translatedexpertise = mapExpertiseLevel(itemData.expertise);
                    $item("#text129").text = translatedexpertise;
                    
                    $item("#button4").disable();
                    $item("#button4").hide();

    // Now show and re-enable the button to clear any previous event bindings
                    $item("#button4").show();
                    $item("#button4").enable();

                    $item("#button4").onClick(async () => {
                        console.log("Button clicked, preparing to call backend...");

                        try {
                            // Convert iresa to integer
                            const iresaCode = parseInt(itemData.iresa, 10);
                            console.log("Raw startDate:", itemData.startDate);
                            console.log("Raw endDate:", itemData.endDate);

                            const startDate = new Date(itemData.startDate);  // Ensure it's a Date object
                            const endDate = new Date(itemData.endDate);      // Ensure it's a Date object

                            // Format startDate and endDate to 'YYYY-MM-DD' format
                            const formattedStartDate = formatDateToISO(startDate);
                            const formattedEndDate = formatDateToISO(endDate);

                            console.log(formattedStartDate, formattedEndDate, "955438", dob, iresaCode.toString());

                            const backendResponse = await sendGraphQLQuery(
                                formattedStartDate,  // Use the ISO-formatted date here
                                formattedEndDate,    // Use the ISO-formatted date here
                                dob,
                                iresaCode  // Use the integer iresaCode here
                            );

                            // Use JSON.stringify to properly log the backend response
                            console.log("Backend response:", JSON.stringify(backendResponse, null, 2));

                            if (backendResponse) {
                                console.log("Setting session storage:", JSON.stringify(backendResponse, null, 2));
                                wixStorage.session.setItem('minimumDeposit', JSON.stringify(backendResponse.minimumDeposit));
                             
                                wixStorage.session.setItem('originalValue', JSON.stringify(backendResponse.originalValue));
                                wixStorage.session.setItem('arrivalEveAvailability', JSON.stringify(backendResponse.arrivalEveAvailability));
                                wixStorage.session.setItem('arrivalEvePrice', JSON.stringify(backendResponse.arrivalEvePrice));
                               

                                // Log the stored values to verify they are set
                                console.log("Stored minAge:", itemData.minAge.toString());
                                console.log("Stored maxAge:", itemData.maxAge.toString());
                                console.log("Code:", iresaCode);
                                console.log("Expertise:", translatedexpertise);

                                // Construct and log the redirection URL
                                const detailsUrl = `https://test/general-5-1`;
                                console.log("Redirecting to:", detailsUrl);

                                // Redirect or handle further logic
                                wixLocation.to(detailsUrl); // Navigate to the new page with the response data
                            }
                        } catch (error) {
                            console.error("Failed to communicate with backend:", error);
                        }
                    });
                }
            });
        })
        .catch(err => {
            console.error('Error querying data:', err);
            throw new Error(err);
        });
}

// Call applyFilters when the page loads to populate the repeater initially
applyFilters();

// Add change event listeners to each dropdown
$w("#dropdown1").onChange(() => applyFilters());  // Activity
$w("#dropdown3").onChange(() => applyFilters());  // Age Range
$w("#dropdown4").onChange(() => applyFilters());  // Month
$w("#dropdown5").onChange(() => applyFilters());  // Budget
$w("#dropdown6").onChange(() => applyFilters());  //

});

Every time you apply a filter, the repeaters’ item data change, but (I think) the items don’t necessarily reload

This means, the buttons get more onClick triggers stacked on them for each filter applied

$w.Button.disable() does not remove the button’s onClick triggers, simply disabled the user’s ability to click it

Instead, you should probably connect the repeater to a dataset, rather than manually querying data from the CMS.
Use wixData.Dataset.filter(wixData.filter().eq(...). ...) and $w.Repeater.onItemReady() to apply the buttons’ functionality

That would reload the repeater’s items and recreate the buttons with fresh onClick behavior every time you filter the dataset