Have only "x" number of items in a repeater display on the page

Hello!

I’ve seen variations of this question asked in the forum but I couldn’t find any answers.

I have a list repeater of 50 items which contains people’s information. The repeater is connected to a data-set on a dynamic page. I have currently have code so that when the page loads, the data-set is shuffled and the 50 items are in a different order every time (so it’s not always the same people at the top of the repeater list). I also have two search bars that filter the data - one filters by person’s name, and one filters by email.

However, I do not want to display all 50 items at once, only 10 random items.

The most common answer to this question is to limit the number of items to display by going into data-set settings in the editor, and selecting the option manually. However, I’ve noticed a couple of problems with this.

The same 10 items will always appear no matter what (I do not want the same people appearing every time someone loads the page). Additionally, the search filters will ONLY work on the 10 items that are being displayed, and not on the rest of the data-set.

Is there a line of code that I can throw in somewhere that tells the repeater to only populate with 10 random data-set items, while still being able to use the search filter to search the other 50 items?

Here is my code:

$w.onReady(async function () {
$w("#dynamicDataset").onReady(async() => {
$w("#dynamicDataset").setFilter( wixData.filter()
.eq("isVerified", "yes")
)
.then( (results) => {
$w('#listRepeater').show();
let repeaterItems = $w('#listRepeater').data;
$w('#listRepeater').data = shuffle(repeaterItems);
} )
.catch( (err) => {
let errorMsg = err;
} );
});
});

function shuffle(items) {
var currentIndex = items.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = items[currentIndex];
items[currentIndex] = items[randomIndex];
items[randomIndex] = temporaryValue;
}
return items;
}

//applies filter to data-set so people can search items by first name and email
function filter() {
$w('#dynamicDataset').setFilter(
wixData.filter()
.contains("firstName", $w("#input2").value)
.and( wixData.filter()
.contains("shortTextField2", $w("#input1").value)
.and(wixData.filter()
.contains("isVerified","yes"))
)
);
}

Thanks in advance for any help!

https://www.wix.com/corvid/reference/wix-dataset.html

Dataset Pages
Datasets retrieve information from your collections in chunks of items. Each of these chunks is called a page.

A dataset’s page size determines how many items are initially displayed in repeaters that are connected to it. Elements that have their own settings for how many items are shown at once, such as tables and galleries, are not affected by the dataset’s page size.

Elements that display data from the dataset’s current item, such as images and text elements, are affected when you change the current dataset page because the dataset’s current item also changes.

You set the page size of a dataset:

  • In the Editor using the Number of items to display setting in the Dataset Settings panel.

  • In code using the setPageSize() function.

https://www.wix.com/corvid/reference/wix-dataset.Dataset.html#setPageSize

setPageSize( )
Sets the dataset’s page size.

Description
The setPageSize() function returns a Promise that is resolved when:

  • The current item is saved in the collection (if necessary).

  • The dataset’s page size is reset.

  • The dataset is refreshed, and any connected elements have been updated.

Because setting the page size refreshes the dataset, the dataset’s current item is reset to the first item in the dataset.

Calling setPageSize() on a write-only dataset causes an error.

Examples
Set a dataset’s page size

$w("#myDataset").setPageSize(6)
  .then( () => {
    console.log("Page size set.");
  } )
  .catch( (err) => {
    let errMsg = err.message;
    let errCode = err.code;
  } );

The problem with this that I’ve found, is that it will always take the same first “x” amount (in this case 6) from within the data-set. I want to be able to display 6 random out of the 50 total. How would I go about doing that?

From above:

" Because setting the page size refreshes the dataset, the dataset’s current item is reset to the first item in the dataset."

This is exactly what I DIDN’T need. Can someone help me out?

After several long hours, I have found a solution/workaround that I want to provide for anyone experiencing this same issue in the future. I hope the following can help you in someway. I’ll do my best to explain the code for all you non-coders out there like me.

$w.onReady(async function () {
$w("#dynamicDataset").setPageSize(5); //limits the repeater to only loading 5 items
$w("#dynamicDataset").onReady(async() => {
$w("#dynamicDataset").setFilter( wixData.filter()
.eq("isVerified", "yes") //I have a column in my dataset called isVerified and I only want verified items to show, so I'm setting a filter
)
.then( (results) => {
let repeaterItems = $w('#listRepeater').data;
$w('#listRepeater').data = shuffle(repeaterItems); //shuffles repeater items
$w('#listRepeater').show();
/*below is what will randomize the 5 items that you show (or else it will show the same 5 everytime). I currently have 58 items in my dataset, and I am showing 5 per page, which is why I chose 53 as my maximum random number (58-5=53)*/
let pageSize = 5;
let random = Math.floor((Math.random() * 53) + 1);
let index = $w("#dynamicDataset").getCurrentItemIndex();
$w("#dynamicDataset").setCurrentItemIndex(random + pageSize)
});
});
});

//shuffles the dataset, you do not need to change anything here
function shuffle(items) {
var currentIndex = items.length, temporaryValue, randomIndex;
while (0 !== currentIndex) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
temporaryValue = items[currentIndex];
items[currentIndex] = items[randomIndex];
items[randomIndex] = temporaryValue;
}
return items;
}

/*I have a randomize button that will show a new random 5 items. This won't shuffle the order of the items, it will just populate the repeater with a different index range. For example, if your repeater was showing items 4-9 in the dataset, if you hit this button, it might then show items 8-13 (it will be a random range from within your dataset). This may not be the PERFECT solution, but it will appear to most of your users that this button is shuffling items (especially if you have a large dataset)*/
export function button1_click(event, $w) {
let random = Math.floor((Math.random() * 53) + 1);
let index = $w("#dynamicDataset").getCurrentItemIndex();
$w("#dynamicDataset").setCurrentItemIndex(random + pageSize);
}

I hope this helps you! The only things that you need to change for your own code would be:

  • Data-set name
  • Repeater name
  • Button on_click function name
  • and the length of your data-set and the number of items you want to appear on each page

#1 Why are you doing this on a dynamicPage - dynamic pages are intended for detail page generation.

#2 Datasets are intended to be used to deliver pages of data in a particular order.

what you should do is load all of the ids in the data collection into a local array. Then use the array to randomly generate a list of items to retrieve from the data collection using wixData.hasSome()

https://www.wix.com/corvid/reference/wix-data.WixDataQuery.html#hasSome