hous
hous

Reputation: 2679

How to update pagination template of knppaginatorbundle after ajax query

Im using knppaginatorbundle to create pagination. I have created a jquery code to select data with ajax.

Everything is okay when I click on the page number , the content is loaded with the correct data. But I have a problem , The pagination template is not changed after after ajax query:

How can I do this ?

public function listAction($page, Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $paginator = $this->get('knp_paginator');
    $qb = $em->getRepository('AppBundle:Travel')->getListTravels();
    $pagination = $paginator->paginate(
        $qb, $request->query->get('page', $page), 3
    );

    //ajax request
    if ($request->isXmlHttpRequest()) {

        $view = $this->renderView('@App/Frontend/Travel/list.html.twig', array(
            'pagination' => $pagination
        ));

        $response = new JsonResponse(array('ok' => $view));
        return $response;
    }

    return $this->render('AppBundle:Frontend/Travel:travel-list-view.html.twig', array(
        'pagination' => $pagination,
    ));
}

I have added an attr data-target to pagination template like this:

<a data-target="{{ page  }}" href="{{ path(route, query|merge({(pageParameterName): page})) }}">{{ page }}</a>

View

//.....
<div id="mydiv">

   // list.html.twig contains the loop
   {% include "AppBundle:Frontend/Travel:list.html.twig" %}

</div>
<br>
{{ knp_pagination_render(pagination) }}
//....

    <script>
    $(document).ready(function () {

        $("ul#pagination a").click(function (e) {
            e.preventDefault();
            var dataTarget = $(this).attr("data-target"); // each <a> has attr named data-target contains num of page
            var hash;
            hash = 'page=' + dataTarget;
            window.location.hash = hash;

            if (window.location.hash != "") {

                $.ajax({
                    type: 'get',
                    dataType: 'json',
                    url: Routing.generate('frontend_travels_list', {'page': dataTarget}),
                    success: function (msg) {
                        if (msg["ok"] === undefined) {
                            alert('error');
                        } else {
                            $("#mydiv").html(msg["ok"]);
                        }
                    }
                });
            }

        });

    });
</script>

Route

frontend_travels_list:
path:     /travels/{page}
defaults: { _controller: AppBundle:TravelFrontend:list, page: 1 }
options:
    expose: true

Upvotes: 1

Views: 2716

Answers (1)

sabat
sabat

Reputation: 146

If someone else needs a solution there 2 ways.

  1. You can use that bundle https://github.com/nacholibre/knppaginator-ajax

  2. You should build new pagination string in controller and send it in JsonResponse as a param. Then replace pagination element in DOM via jQuery on success.

For SF 4.3 you can use my approach

  1. To be able to inject the Processor in controller you have to add alias for autowiring in services.yaml
Knp\Bundle\PaginatorBundle\Helper\Processor: '@knp_paginator.helper.processor'
  1. Based on injected PaginatorInterface you should build your $pagination object (PaginationInterface)

  2. Use Processor to build the context array for Twig.

$paginationContext = $processor->render($pagination);

render method expects SlidingPagination object, but got $pagination which is PaginationInterface - however it seems that is ok

  1. Get the Twig and render a final string
$twig = $this->get('twig');
$paginationString = $twig->render($pagination->getTemplate(), $paginationContext);

Example of working controller

if ($request->isXmlHttpRequest()) {
    $view = $this->render('@App/Frontend/Travel/list.html.twig', array(
        'pagination' => $pagination
    ))->getContent();
    $paginationContext = $processor->render($pagination);
    $twig = $this->get('twig');
    $paginationHtml = $twig->render($pagination->getTemplate(), $paginationContext);
    $response = new JsonResponse(['view' => $view, 'paginationHtml' => $paginationHtml]);
    return $response;
}

then in jQuery

success: function (msg) {
    if (msg["ok"] === undefined) {
        alert('error');
    } else {
        $("#mydiv").html(msg["view"]);
        $("#myDivContainingPagination").html(msg["paginationHtml"])
    }
}

Upvotes: 2

Related Questions