Gift Quiz Results - Limit number of items displayed in recommendedProducts repeater

Hello Velo World!

I am working with the Gift Quiz example from here: https://www.wix.com/velo/example/gift-quiz

I’ve been able to replicate it perfectly and it works wonderfully on a couple sites. However, what is not clear is how to limit the results, eg So that the final number of results displayed in the #recommendedProducts repeater is never more than 3 (or 4 max or 5 max etc)

In the Gift Quiz Tutorial video (timestamp 08:15 ) on line 91 he instructs us to:

“set the maximum numberOfItems to the maximum numberOfSlides in the quiz or 4. Then…”

To me the above statement implies the user will never get more than 4 recommended products at the end of the quiz (because there are 4 slides in the example). But I’ve tested out the example site multiple times and I will often get more than 4 products at the end (up to 10 sometimes, actually). He also says that the numberOfItems argument is the “maximum number of items the customer will see in the repeater” but it’s unclear how to limit this number. What if I have 9 slides in my quiz but only want 3 products max to show at the end, regardless? How do we do that?

The answer to my question must lie somewhere in lines 90-108 (placed in bold in the below code). The getRandomItemsFromArray function is supposed to " randomly select a predefined number of matching arguments ", but I am not clear where or how it sets the “predefined number of matching arguments”. I am not a beginner coder, but obviously something is eluding me here. I would greatly appreciate if anyone else has any guidance!

//-------------Imports-------------//

import wixData from 'wix-data';

//-------------Global Variables-------------//

// List of selected answers.
const selectedAnswers = [];
// List of IDs of all the answer buttons.
const quizAnswersIds = ["bestie", "girlfriend", "myself",
 "surpriseMe", "accessories", "clothing", "beauty",
 "surpriseMe2", "gold", "red", "lavender"
];
// Number of questions plus one for the results.
let numberOfSlides;

//-------------Page Setup-------------//

$w.onReady(() => {
 // Set the global numberOfSlides variable from the slideshow length.
    numberOfSlides = $w('#quizSlides').slides.length;
 
 // For each answer button:
    quizAnswersIds.forEach(answer => {
 // Set the action that occurs when a user clicks the answer button.
        $w(`#${answer}`).onClick(() => {
 // Add the answer to the global selected answers list.
            selectedAnswers.push(answer);
 // Move to the next slide.
            $w('#quizSlides').next();
        })
    })
});

//-------------Quiz Finish-------------//

// Set the action that occurs when a user is moved to the next slide.
export async function quizSlides_change(event, $w) {
 // If the quiz is finished:
 if (isQuizFinished()) {
 // Get the keywords associated with each product by calling the getKeywordsPerProduct() function.
 let quizProducts = await getKeywordsPerProduct();
 // For each selected answer:
        selectedAnswers.forEach(answer => {
 // Filter out the products that do not match the answer.
            quizProducts = filterProductsPerAnswer(quizProducts, answer);
        });
 // Extract the product IDs from the filtered product.
        quizProducts = quizProducts.map(quizProduct => quizProduct.productId);
 // Get a random list from the remaining filtered products.
        quizProducts = getRandomItemsFromArray(quizProducts, numberOfSlides);
 // Populate the recommended products repeater with the product data that corresponds to the randomly selected products.
        $w('#recommendedProducts').data = await getProductsData(quizProducts);
    }
}

// Checks if the quiz has been completed.
function isQuizFinished() {
 // Check if the current slide is the last slide.
 return $w('#quizSlides').currentIndex === numberOfSlides - 1;
}

// Get the keywords associated with each product.
async function getKeywordsPerProduct() {
 // Query the "productsKeywords" collection for the product keywords.
 let productsKeywords = await wixData.query("productsKeywords").find();
 // Extract the items from the query results.
    productsKeywords = productsKeywords.items;
 // Process the returned item data to make it easier to work with.
    productsKeywords = productsKeywords.map(item => {
 return {
            productId: item.product,
            keywords: item.keywords.split(",")
        }
    });
 // Return the processed item data.
 return productsKeywords;
}

// Filter out products that don't match the specified answer. 
function filterProductsPerAnswer(quizProducts, answer) {
 // Use the JavaScript filter() function to filter out products that don't match the specified answer. 
 const filteredProducts = quizProducts.filter(quizProduct => {
 return quizProduct.keywords.includes(answer)
    });
 // Return the filtered product list.
 return filteredProducts;
}

// Get a specified number of random items from the specified array.
function getRandomItemsFromArray(productsArr, numberOfItems){
 // List for storing the randomly selected products.
 const productsIds = [];
 // Number of products in the specified array.
 const numberOfProducts = productsArr.length;

 // For specified the number of items or the number of products that were specified, whichever is lower: 
 for (let i = 0; i < (numberOfItems && i < numberOfProducts); i++){
 // Get a random valid index.
 const randomIndex = getRandomInt(0, numberOfProducts -1 );
 // Add the product at that random index to the list of selected products.
        productsIds.push(productsArr[randomIndex]);
 // Remove the already selected product from the list of products to select from.
        productsIds.splice(randomIndex, 1);
    }
 // Return the randomly selected products.
 return productsIds;
}

// Get a random number between two specified values.
function getRandomInt(min, max) {
 // Use JavaScript math functions to get a random number between two specified values.
 return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Get the product data associated with the specified product IDs.
async function getProductsData(productsIds) {
 // Query the "Products" collection for products whose ID is one of the specified IDs.
 const productsData = await wixData.query("Stores/Products")
        .hasSome("_id", productsIds)
        .find();
 // Return the matching products.
 return productsData.items;
}

// Set up each item in the recommended products repeater when it receives data as the quiz is finished.
export function recommendedProducts_itemReady($item, itemData, index) {
 // Populate the elements from the current item's data.
    $item('#name').text = itemData.name;
    $item('#image').src = itemData.mainMedia;
    $item('#image').link = itemData.productPageUrl;
    $item('#price').text = itemData.formattedPrice;
}

Unfortunately, most of the other threads in the forum are surrounding confusion in some differences in the Velo Gift Quiz Example tutorial and video tutorial itself found here and the Wix Support Article found here. And I feel my question has never been properly addressed, so I’m starting a new thread :slight_smile:

In another thread here, a Wix Administrator suggested looking at the limit( ) function on the data query, but when I tried that (eg. .limit(3), what happens is that the quiz appears to work but then you always get the same 3 products results at the end of the quiz, regardless of answers selected. So that feels like a dead end to me.

Help would be greatly appreciated!