Dynamic limit per page Knp Pagination

Ehsan picture Ehsan · Mar 10, 2014 · Viewed 7.9k times · Source

I need straightforward solution for dynamically set number of records per page with Knp Pagination Bundle.

I read the this page records per page allow user to choose - codeigniter pagination about dynamically set per page limits and I know I need a drop down with hyperlink inside each item that send a request to server and server use parameter on this request to set limit per page on knp pagination bundle. But I don't know exactly how to handle this actions on server and also and more harder to me how to create items on drop down related to the total number on my query.

my controller:

public function indexAction()
{   
    $page_title = Util::getFormattedPageTitle("Customers");

    $em    = $this->get('doctrine.orm.entity_manager');
    $dql   = "SELECT a FROM CustomersBundle:Customer a WHERE a.enable = 1 ORDER BY a.id";
    //$query = $em->createQuery($dql);
    //$customers = $query->execute();

    $query = $em->createQuery($dql); 
    $paginator  = $this->get('knp_paginator');
    $pagination = $paginator->paginate(
        $query,
        $this->get('request')->query->get('page', 1)/*page number*/,
        3/*limit per page*/
    );


    // parameters to template
    return $this->render('CustomersBundle:Default:index.html.twig', array(
        'page_title' => $page_title,
        'pagination' => $pagination,
        'image_path' => CustomersConstants::$customers_image_thumb_path
    ));
}

And my view code is:

    {% extends '::base.html.twig' %}

{% block title %}
    {{ page_title }}
{% endblock %}

{% block body %}
    <h1>
        {{ "customers" }}
    </h1>
    <br />
    {% for customer in pagination %}
    <a href="{{ customer.url }}" target="_blank">
        <div dir="rtl" class="st_simple_box" id="customer{{customer.id}}" >
            <table cellpadding="0" cellspacing="0" width="100%">
                <tr>
                    <td style="vertical-align: top; width: 115px;">
                        {% if customer.imageName is not empty %}
                            <img class="newsimage" src="{{asset(image_path) ~ customer.imageName}}" alt="No Image/>
                        {% else %}
                            <img class="newsimage" src="{{asset('images/vakil_default_small.png') ~ customer.imageName}}" alt="No Image"/>
                        {% endif %}
                    </td>
                    <td style="text-align: center;">
                        <p><span style="font-family: Tahoma;">{{customer.titleFa}}</span></p>
                    </td>
                    <td style="text-align: justify;">
                        <p><span style="font-family: Tahoma;">{{customer.descriptionFa}}</span></p>
                    </td>
                </tr>
            </table>
        </div>
    </a>
    {% endfor %}
    <div class="navigation">
        <span>
        {{ knp_pagination_render(pagination) }}
        </span>
        <!--Here is my drop down html code-->
    </div>
    <br />

{% endblock %}

**

Edited on 12 March 2014

   ||||
   ||||
   ||||
  \\\///
   \\//
    \/

Is there any way to set MaxItemPerPage on cookie to have a integrated variable and use this variable or change it while Knp Pagination is showed up on twig file.

the answer was correct but because of I used pagination in many bundles to paginate between my entities so I need an integrate variable to change all of them. I use your answer and customize sliding.html.twig on Knp Pagination to reach this code for "customized_sliding.html.twig"

<div class="ui small pagination menu">
    <div style="clear: both;">
        {% if pageCount > 1 %}
            <div class="pagination" style="float: right;">
                {% if first is defined and current != first %}
                    <a href="{{ path(route, query|merge({(pageParameterName): first})) }}" class="small icon item">
                        <i class="small double angle right icon"></i>
                    </a>
                {% endif %}

                {% if previous is defined %}
                    <a href="{{ path(route, query|merge({(pageParameterName): previous})) }}" class="small icon item">
                        <i class="small angle right icon"></i>
                    </a>
                {% endif %}

                {% for page in pagesInRange %}
                    {% if page != current %}
                        <a href="{{ path(route, query|merge({(pageParameterName): page})) }}" class="small item">
                            {{ page }}
                        </a>
                    {% else %}
                        <a class="small active item">
                            {{ page }}
                        </a>
                    {% endif %}
                {% endfor %}

                {% if next is defined %}
                    <a href="{{ path(route, query|merge({(pageParameterName): next})) }}" class="small icon item">
                        <i class="small angle left icon"></i>
                    </a>
                {% endif %}

                {% if last is defined and current != last %}
                    <a href="{{ path(route, query|merge({(pageParameterName): last})) }}" class="small icon item">
                        <i class="small double angle left icon"></i>
                    </a>
                {% endif %}
            </div>
        {% endif %}
        <div style="float: left;">
            <select name="maxItemPerPage" id="maxItemPerPage">
                <option selected="true" style="display:none;">Number Per Page</option>
                <option id="10">5</option>
                <option id="20">10</option>
                <option id="30">20</option>
            </select>
        </div>
    </div>
    <script type="text/javascript">
        //on select change, you navigate to indexAction and send the parameter maxItemPerPage
        $('#maxItemPerPage').change(function(){
            {% set currentPath = path(app.request.attributes.get('_route')) %}
            var url = "{{path(app.request.attributes.get('_route'),{'maxItemPerPage': '_itemNum'})}}";
            var item = $('#maxItemPerPage').find(":selected").text();
            jQuery(location).attr('href', url.replace('_itemNum',item ));
        });
    </script>
</div>

I want to fetch and store MaxItemPerPage from cookie so there is no need to change all bundles code. For example in my controller I don't know have to fetch the $maxItemPerPage from cookie

$pagination = $paginator->paginate(
            $query,
            $this->get('request')->query->get('page', 1)/*page number*/,
            $maxItemPerPage/*limit per page*/
        );

And I need change the value of maxItemPerPage on cookie by changing the value of html tag by javascript and redirect the page to same controller and no need to send maxItemPerPage to controller.

Answer

Chopchop picture Chopchop · Mar 10, 2014

This can be done easily (if i understood well)

public function indexAction($maxItemPerPage=20)
{   
    $page_title = Util::getFormattedPageTitle("Customers");

    $em    = $this->get('doctrine.orm.entity_manager');
    $dql   = "SELECT a FROM CustomersBundle:Customer a WHERE a.enable = 1 ORDER BY a.id";
    //$query = $em->createQuery($dql);
    //$customers = $query->execute();

    $query = $em->createQuery($dql); 
    $paginator  = $this->get('knp_paginator');
    $pagination = $paginator->paginate(
        $query,
        $this->get('request')->query->get('page', 1)/*page number*/,
        $maxItemPerPage /*limit per page*/
    );


    // parameters to template
    return $this->render('CustomersBundle:Default:index.html.twig', array(
        'page_title' => $page_title,
        'pagination' => $pagination,
        'image_path' => CustomersConstants::$customers_image_thumb_path
    ));
}

in the view

   {% extends '::base.html.twig' %}

    {% block title %}
        {{ page_title }}
    {% endblock %}
{% block javascript%}
<script type="text/javascript">

//on select change, you navigate to indexAction and send the parameter maxItemPerPage
$('#maxItemPerPage').change(function(){

var url = '{{path('controller_index_route','maxItemPerPage':_itemNum)}}';
var item = $('#maxItemPerPage').find(":selected").text();

window.location.href = url.replace('_itemNum',item );
})

</script>
    {% endblock %}

    {% block body %}
        <h1>
            {{ "customers" }}
        </h1>
        <br />
        {% for customer in pagination %}
        <a href="{{ customer.url }}" target="_blank">
            <div dir="rtl" class="st_simple_box" id="customer{{customer.id}}" >
                <table cellpadding="0" cellspacing="0" width="100%">
                    <tr>
                        <td style="vertical-align: top; width: 115px;">
                            {% if customer.imageName is not empty %}
                                <img class="newsimage" src="{{asset(image_path) ~ customer.imageName}}" alt="No Image/>
                            {% else %}
                                <img class="newsimage" src="{{asset('images/vakil_default_small.png') ~ customer.imageName}}" alt="No Image"/>
                            {% endif %}
                        </td>
                        <td style="text-align: center;">
                            <p><span style="font-family: Tahoma;">{{customer.titleFa}}</span></p>
                        </td>
                        <td style="text-align: justify;">
                            <p><span style="font-family: Tahoma;">{{customer.descriptionFa}}</span></p>
                        </td>
                    </tr>
                </table>
            </div>
        </a>
        {% endfor %}
        <div class="navigation">
            <span>
            {{ knp_pagination_render(pagination) }}
            </span>
            <!--Here is my drop down html code-->
        </div>
        <br />
<select name="maxItemPerPage" id="maxItemPerPage">
<option id="10">10</option>
<option id="20">20</option>
<option id="30">30</option>
</select>

    {% endblock %}