How do I get next page after filtering a query callback?

I’m using data query to do filtering as I have array of objects in one of the field and dataset wouldn’t make the cut to filter correctly. Is there an API of something that I can do to find next page without requery the entire collection again?

wixData.query("collection")
 .skip(skip)
 .ascending('name')
 .limit(6)
 .find()
 .then( (results) => { 
    //let dataset = Manipulation of results
    //How do I determine if the results after manipulation has next page?
 });

Hello again, @samuellmkit :raised_hand_with_fingers_splayed:

The best way is to get the next page in advance and examining it, then decide if there’s a next page or not.

wixData.query("collection")
 .skip(skip)
 .ascending('name')
 .limit(6)
 .find()
 .then(async (results) => { 
    const { items, length, totalCount } = results;
    // show the current results.
    // .........................
    
    // Fetch the next items and determine whether there's a next page or not
    if (results.hasNext()) {
       // Get the next page of results
       const temp = await results.next();
       
       // Store the next page for later
       
       /* Examine the new items, if at least one item passed your examination
       then the results above have a next page. */       
    } else {
       // If the results don't have a next page, show no next page.
    }
 });

Hope this helps~!
Ahmad

dear @ahmadnasriya , I am wondering then how you actually make the user to to the next page…here we are generating the next page, if one, but how do we get to actually go there? Also, does this work with multiple next pages? Thank you!

You can just feed a repeater, with the new data generated by the .next() method.

import wixData from 'wix-data'

$w.onReady(async () => {
    let data = await wixData.query("collection").ascending('name').limit(6).find()
    if (data.hasNext()) { // if it has more than 6 items in the dataset
        const nextData = await data.next() // this command gets the next 6 items and stores them in nextData
        console.log(nextData)
    } else {
        console.log("No more data")
    }
})

Dear Bruno… in your code we are saving the next results to the const nextdata. So then we would need to add a next button with an onClick event that feed the repeater on the page with the nextData? But how will this manage multiple next pages of result?

You should maintain a global constant to store all the items, next and previous ones too.

const results = {
    prev: [],
    current: [],
    next: [],
    page: 1 // The current page
}

When the page first load, the results must be stored in the current items, and the next results in the next items.

function search(type) {
    if (!type) { type = 'current' }
    const page_size = 20; // 20 items to display at a time.
    let skip;
    if (type === 'prev') { skip = (results.page - 2) * page_size }
    if (type === 'current') { skip = (results.page - 1) * page_size }
    if (type === 'next') { skip = (results.page) * page_size }    

    query('collection').skip(skip).limit(page_size).find().then(async(x) => {
        results[type] = x.items;
        return Promise.resolve();
    }).then(() => {
        // Enable OR disable buttons
        results.next.length > 0 ? $w('#nextBtn').enable() : $w('#nextBtn').disable();
        results.prev.length > 0 ? $w('#prevBtn').enable() : $w('#prevBtn').disable();
        return Promise.resolve();
    })
}

And when the visitor clicks on the Next button, you should change the results’ data around, make the current items the previous ones, and the next ones the current ones, then fetch the new items skipping the current items.

$w('#nextBtn').onClick(() => {
    
    
    // Update the current items;
    $w('#repeater').data = results.current;
    results.prev = results.current;
    results.current = results.next;
    
    // Empty the next items
    results.next = [];
    
    // Fetch the next page.
    search('next').then(() => {
        // Update the current page number;
        results.page > 1 ? results.page++ : null;
    })
})

Similarly, you can code the previous button.

@ahmadnasriya this is quite amazing! Still the same user, for some reason my other account is not authorized to post anything with link or code inside…
So there is quite a lot to metabolize for me here… just a couple of quick questions:

This code is in combination with the previous code that you posted on this same thread correct? OR the three pieces are standalone? I have the following code that I would like to integrate with the next button function that you gave me.

In my code the queries are launched by searchboxes with the results going to repeater 1. I have some problems understanding where your code would play into mine!

import {local} from 'wix-storage'
import wixData from 'wix-data';

$w.onReady(function () {
    $w("#searchBar").value = "";
    $w("#searchBar").placeholder = "calcium, ER, Hajnockzy...";
    });

$w.onReady(function () {
    $w("#repeater1").onItemReady(($item, itemData, index) => {
        $item("#text59").text = itemData.title;
        $item("#text57").text = itemData.authors;
        $item("#text58").text = itemData.sourceTitle;
        $item("#text60").text = String(itemData.year);
        $item("#text63").text = itemData.documentType;
        $item("#button1").link = itemData.link;
     });

    wixData.query("MitoCarePublications")
        .descending("year")
        .limit(10)
        .contains("authors", "tigano")
        .find()
        .then( (results) => {
            if(results.items.length > 0) {
                $w("#repeater1").data = results.items;
                let resultspages = results.pageSize
                let items = results.items;
                let firstresult = items[0]
                let firsttitle = firstresult.title
                let firstyear = firstresult.year
                let resultsnumber = results.totalCount
                    if (resultsnumber > 1) {
                        $w('#counter').text = `${resultsnumber} results were found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 1) {
                        $w('#counter').text = `${resultsnumber} result was found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 0) {
                        $w('#counter').text = "No result found!";
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                console.log(items[0])
                console.log(firsttitle)
                console.log(firstyear)
            }   else {
                console.log("noresults")    
            $w("#searchGIF").hide();
            }
        })
})

export function searchButton_click(event) {
        search();
    }

function search() {
    $w('#searchGIF').show();
    let keywords = $w("#searchBar").value
    wixData.query("MitoCarePublications")
        .descending("year")
        .limit(10)
        .contains("title", keywords)
        .or(
            wixData.query("MitoCarePublications")
                .descending("year")
                .contains("sourcetitle", keywords)
        )
        .find()
        .then( (results) => {
            if(results.items.length > 0) {
                $w("#repeater1").data = results.items;
                let resultsnumber = results.totalCount
                    if (resultsnumber > 1) {
                        $w('#counter').text = `${resultsnumber} results were found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 1) {
                        $w('#counter').text = `${resultsnumber} result was found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 0) {
                        $w('#counter').text = "No result found!";
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
            }   else {
                console.log("noresults")
            $w("#searchGIF").hide();
            }
        });
}
export function resetButton_click(event) {
        reset();
    }

function reset() {
    $w('#searchGIF').show();
    $w("#searchBar").value = "";
    $w("#searchBar").placeholder = "calcium, ER, Hajnockzy...";
    let keywords = $w("#searchBar").value
    wixData.query("MitoCarePublications")
        .descending("year")
        .limit(10)
        .contains("title", keywords)
        .or(
            wixData.query("MitoCarePublications")
                .descending("year")
                .contains("sourcetitle", keywords)
        )
        .find()
        .then( (results) => {
            if(results.items.length > 0) {
                $w("#repeater1").data = results.items;
                let resultsnumber = results.totalCount
                    if (resultsnumber > 1) {
                        $w('#counter').text = `${resultsnumber} results were found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 1) {
                        $w('#counter').text = `${resultsnumber} result was found.`;
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
                    if (resultsnumber === 0) {
                        $w('#counter').text = "No result found!";
                        $w("#searchGIF").hide();
                        $w('#counter').show();
                    }
            }   else {
                console.log("noresults")
            $w("#searchGIF").hide();
            }
        });
}