PaulCatalin
PaulCatalin

Reputation: 13

jQuery Pagination shows two page buttons for one page of content

I'm using a table to show the values from my database and I use a JQuery for pagination. This is working overall. When there is only one page of results, however, the pagination shows:

for 1 page of data it looks like this

This isn't what I want; the link to Page 1 should only be displayed once.

When it shows data for more pages, it works fine:

works fine like this for multiple pages

Here is the code for the table and the buttons

function getProducts() {
    $.get('/get-products', parameters).then(res => {
        console.log(res);
        let products = res.data;
        preview = res.current_page > 1 ? true : false;
        next = res.current_page < res.last_page ? true : false;
        preview ? $('#previous').removeAttr("disabled") : $('#previous').attr('disabled', 'disabled');
        next ? $('#next').removeAttr("disabled") : $('#next').attr('disabled', 'disabled');
        let table_body = $('#tbody');
        table_body.empty();
        var html = '';
        $.each(products, function(index, val) {
            html += "<tr> " +
                "<td>" + val.name + "</td>" +
                "<td>" + val.quantity + "</td>" +
                "<td>" + val.price +"<p> Lei </p>"+"</td>" +
                "<td>" + val.status.name + "</td>" +
                "<td>" + val.description + "</td>" +
                "<td>" + val.technics + "</td>" +
                "<td>" + "<a class='btn btn-warning' href='/editareprodus/"+ val.id +"'>Edit</a>" + "</td>" +
                "<td>" + "<a class='btn btn-danger' onclick=deleteItem("+ val.id +")>Delete</a>" + "</td>" +
            "</tr>";
        });
        table_body.append(html);
        $('.page_button').remove();
        var buttons = '';
        for(var i = 1; i < res.last_page+1; i++) {
            if(i == 1) {
                if(i == res.current_page) {
                    buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                } else{
                    buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                }
            }
            if(i == res.last_page) {
                if(i == res.current_page) {
                    buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                } else{
                    buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                }
            }
            if(i == res.current_page-2 && res.current_page-2 >= 2 ) {
                buttons += '<span class="page_button">...</span>';
            }
            if(i == res.current_page+2 && res.current_page+2 < res.last_page) {
                buttons += '<span class="page_button">...</span>';
            }
            if((i != 1 && i != res.last_page) && (i == res.current_page-1 || i == res.current_page || i == res.current_page+1)) {
                if(i == res.current_page) {
                    buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                } else {
                    buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter('+i+')">'+i+'</button>';
                }
            }
        }
        $('#previous').after(buttons)
    });
}

I will add the code for the previous and next page button just so you can see them, but these work fine:

function previewPage() {
    if(preview) {
        parameters.page--;
        getProducts();
    }
}

function nextPage() {
    if(next) {
        parameters.page++;
        getProducts();
    }
}

function setPageParameter(page) {
    this.parameters.page = page;
    getProducts();
}

How can I change the code to show me one page button when I have one page, not two buttons as is happening now?

Upvotes: 0

Views: 682

Answers (1)

Jeremy Caney
Jeremy Caney

Reputation: 7625

The issue is due to a problem with the logic within your for loop. You have several conditions under which a button can be written:

  • If the button is the first page; i.e.,

    i == 1
    
  • If the button is the last page; i.e.,

    i == res.last_page
    
  • If the button is immediately before or after the current page, but not the first or the last page; i.e.,

    (i != 1 && i != res.last_page) && (i == res.current_page-1 || i == res.current_page || i == res.current_page+1)
    

The key issue is that the first two are non-exclusive; i.e., when you only have one page, your button can simultaneously represent both the first page as well as the last page. Thus, it's fully expected that you'd see two buttons in that scenario.

Resolving exclusivity

This can easily be resolved by simply changing the logic of the second condition from an if to an else if; e.g.,

if (i == 1) 
{
    if (i == res.current_page) {
      buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    } 
    else
    {
        buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    }
}
else if (i == res.last_page) // Only show if not also the first button
{
    if (i == res.current_page)
    {
        buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    } 
    else
    {
        buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    }
}       

Consolidating logic

The above solves your core issue, but as these generate the exact same markup, you might as well collapse them into a single condition using an || operator, thus maintaining the same results while consolidating the code:

if (i == 1 || i == res.last_page) 
{
    if (i == res.current_page)
    {
        buttons += '<button type="button" class="btn btn-danger page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    } 
    else
    {
        buttons += '<button type="button" class="btn btn-primary page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    }
}

Refactoring for loop

This is well beyond the scope of your original question, but even after consolidating the previous conditions, there's still room for cleanup. That's because, currently, you're repeating a lot of markup within your function.

As a developer, you should strive not to repeat code. Why? Because in addition to making the code longer, it can also make it easier to introduce bugs. For example, if you decide to change the style of the buttons, you need to change them in four places. It’s easy in that situation to inadvertently overlook one, introducing an inconsistency.

Given that, you should be able to further consolidate your logic as something like the following:

for (var i = 1; i < res.last_page + 1; i++) {
    if (i == 1 || i == res.last_page || i == res.current_page - 1 || i == res.current_page || i == res.current_page + 1) {
        buttons += '<span class="page_button">...</span>';
    }
    else if (
        (i == res.current_page - 2 && res.current_page - 2 >= 2) ||
        (i == res.current_page + 2 && res.current_page + 2 < res.last_page)
    ) {
        buttons += '<button type="button" class="btn btn-"' + (i == res.current_page? "danger" : "primary") + '" page_button" onclick="setPageParameter(' + i + ')">' + i + '</button>';
    }
}

This logic could be simplified a bit more, but I've maintained your original expressions for consistency and readability, while refactoring them to avoid the duplication of markup. This not only addresses the original issue, but results in much shorter code block.

Upvotes: 0

Related Questions