Hi guys, I will try to be brief and concise.
I have a repeater displaying items from a Database Collection, using a query.
Furthermore, I have a button on the page that randomly generates these items (I only want 10 items to appear for the user per generation-click
Problem 1: I want to add a button on each displayed item on the page, letting the user lock in the random generated item. So that when they next click the generate button, the locked in item will not be randomized away from the repeater list.
Please see this website for reference of what I mean with the function, where you generate colors and can lock them in.
Bonus Question to P1: I don’t want the item to be locked for ever user, only the user currently randomizing/locking in items should have them locked. Just like on the reference website above.
I’m guessing this will be done with a onClick event (which I’m fairly comfortable with), but I’m not sure how to make the repeater “understand” which ones are locked in. I’ve been dabbing around with some wixData.update functions, but don’t get it to work.
Problem 2 (less complicated I think): When the items are first displayed to the website user, only 10 items appear. But when they press the generateButton, all the items from my database (15 at the moment, but will increase to >1000) appear. How do I limit the repeater even after the generateButton is pressed?
import wixData from 'wix-data';
$w.onReady(async function () {
$w('#mainRepeater').onItemReady(($item, $itemData, index) => {
$item("#questionText").text = $itemData.title;
$item("#answerText").text = $itemData.answer;
$item("#spotifyLink").link = $itemData.songLink;
});
const { items: Questions } = await wixData.query('Questions')
.limit(10)
.find()
$w('#mainRepeater').data = Questions
})
export async function generateButton_click(event) {
$w("#mainRepeater").onItemReady(($item, itemData, index) => {
$item("#questionText").text = itemData.title;
$item("#answerText").text = itemData.answer;
$item("#spotifyLink").link = itemData.songLink;
});
let results = await wixData.query("Questions").find();
let items = results.items;
console.log(items);
let shuffled = shuffleArray(items);
console.log(shuffled); //
$w('#mainRepeater').data = shuffled;
}
function shuffleArray(array) {
for (let last = array.length - 1; last > 0; last--) {
const next = Math.floor(Math.random() * (last + 1));
[array[last], array[next]] = [array[next], array[last]];
}
return array;
}
Thank you in advance!
Hi! When the page loads, initialize an empty array called lockedItems to store the locked items. When the user clicks the lock button for an item, get the data for that item and add it to the lockedItems array using wixData.get. When the user clicks the generate button, use the wixData.query function to retrieve all the items from the database and store them in a variable called allItems. Use the array.filter method to remove the items in lockedItems from allItems. Use the shuffleArray function to shuffle the remaining items in allItems. Set the data for the repeater to the first 10 items in the shuffled array using the $w(‘#mainRepeater’).data property.
Thank you for that bamuu.
I tried following your suggestions and ended up with the following code. However, this does not seem to work. It still shuffles, but when I click the lockButton in my preview nothing happens. Can you see any obvious mistakes?
import wixData from ‘wix-data’ ;
let lockedItems = []; // Initialize an empty array to store locked items
//Hämta data från Databasen med följande kod
$w . onReady ( async function () {
$w ( ‘#mainRepeater’ ). onItemReady (( $item , $itemData , index ) => {
$item ( “#questionText” ). text = $itemData . title ;
$item ( “#answerText” ). text = $itemData . answer ;
$item ( “#spotifyLink” ). link = $itemData . songLink ;
// Add a click event handler to the lock button
$item ( ‘#lockButton’ ). onClick ( async () => {
// Get the current item from the Questions collection
let item = await wixData. get ( “Questions” , $itemData._id);
// Add the current item to the lockedItems array
lockedItems . push ( item );
});
});
**const** { items : Questions } = **await** wixData . query ( 'Questions' )
. limit (10)
. find ()
$w ( '#mainRepeater' ). data = Questions
})
export async function generateButton_click ( event ) {
$w ( “#mainRepeater” ). onItemReady (( $item , itemData , index ) => {
$item ( “#questionText” ). text = itemData . title ;
$item ( “#answerText” ). text = itemData . answer ;
$item ( “#spotifyLink” ). link = itemData . songLink ;
});
// Query the Questions collection to get all items
**let** results = **await** wixData . query ( "Questions" ). find ();
**let** allItems = results . items ;
// Use the array.filter method to remove the items in lockedItems from allItems
**let** availableItems = allItems . filter ( item => ! lockedItems . includes ( item ));
// Shuffle the available items
**let** shuffled = shuffleArray ( availableItems );
// Set the data for the repeater to the first 10 items in the shuffled array
$w ( '#mainRepeater' ). data = shuffled . slice ( 0 , 10 );
}
function shuffleArray ( array ) {
for ( let last = array . length - 1 ; last > 0 ; last --) {
const next = Math . floor ( Math . random () * ( last + 1 ));
[ array [ last ], array [ next ]] = [ array [ next ], array [ last ]];
}
return array ;
}
It looks like there are two issues, lockedItems is not being reset when the generateButton is clicked, so the availableItems array will always be empty. You can fix this by adding lockedItems = [] at the beginning of the generateButton_click function. The lockButton click event handler is not updating the item in the Questions collection.
You can fix this by adding the following code to the click event handler:
await wixData.update("Questions", item);
This will update the item in the Questions collection with the latest version of the item object.
Hmm, the lockedButton still doesn’t do anything for me.
Is the order in which things are happening in my code correct? I’m confused about why the lockButton click even handler is inside onReady function.
This might be correct, but just seems weird to me… Here’s the flow I want the user to have:
I want the initial repeater (when entering the website) to have 10 random items. Then I wan’t the user to be able to randomize 10 other items. Let’s say the press the button 3 times and then find an item they want to save, then they press the lockButton.
The next time they press the generateButton, only the 9 items that are not locked should be randomized again, and the locked item should remain in the repeater (preferable on the same place).
Hi again guys, still not really figuring out how to do this.
I have followed Bamuu’s instructions (I hope) and my current updated code is seen below.
I’m absolutely no expert in Velo (or any code for that matter) so if you have any suggestion on how to make my repeater items lock in place and not be randomized away, I appreciate it if you could explain it to me like I’m a novice.
The problem is still that when I press the “lockButton”, the question isn’t locked. Looking the the console the “get” function seems to work, but I can’t see that the item is pushed to the lockedItems array. This might not be possible to see, I don’t know. But either way, the item still get’s randomized away at the next “generateButton” onClick event.
import wixData from 'wix-data';
let lockedItems = []; // Initialize an empty array to store locked items
//Populate the repeater
$w.onReady(async function () {
$w('#mainRepeater').onItemReady(($item, $itemData, index) => {
$item("#questionText").text = $itemData.title;
$item("#answerText").text = $itemData.answer;
$item("#spotifyLink").link = $itemData.songLink;
// Add a click event handler to the lock button
$item('#lockButton').onClick(async () => {
// Get the current item from the Questions collection
let item = await wixData.get("Questions", $itemData._id);
await wixData.update("Questions", item);
// Add the current item to the lockedItems array
lockedItems.push(item);
console.log(item)
});
});
const { items: Questions } = await wixData.query('Questions')
.limit(10)
.find()
$w('#mainRepeater').data = Questions
})
//Randomzie button onClick event
export async function generateButton_click(event) {
$w("#mainRepeater").onItemReady(($item, itemData, index) => {
$item("#questionText").text = itemData.title;
$item("#answerText").text = itemData.answer;
$item("#spotifyLink").link = itemData.songLink;
});
// Query the Questions collection to get all items
let results = await wixData.query("Questions").find();
let allItems = results.items;
// Use the array.filter method to remove the items in lockedItems from allItems
let availableItems = allItems.filter(item => !lockedItems.includes(item));
// Shuffle the available items
let shuffled = shuffleArray(availableItems);
// Set the data for the repeater to the first 10 items in the shuffled array
$w('#mainRepeater').data = shuffled.slice(0, 3);
}
function shuffleArray(array) {
for (let last = array.length - 1; last > 0; last--) {
const next = Math.floor(Math.random() * (last + 1));
[array[last], array[next]] = [array[next], array[last]];
}
return array;
}
After some consoling and trying back and forth, the problem seems to lie here.
The allItems show up in console as they should. But the “availableItems” are the same items as allItems after clikcing the lockButton. So the allItems.filter doesnt work.
Any idea why?
// Query the Questions collection to get all items
let results = await wixData.query("Questions")
.find();
let allItems = results.items;
console.log(allItems)
// Use the array.filter method to remove the items in lockedItems from allItems
let availableItems = allItems.filter(item => !lockedItems.includes(item));
console.log(availableItems)
// Shuffle the available items
let shuffled = shuffleArray(availableItems);
console.log(shuffled)