I'd like to implement the Knp Pagination for a table.
It is a page where I edit documents, so my route looks like that: @Route("/document/edit/{id}/") and depending on the document, there is a different ID. There are several panels on the page and one of them contains a table of different agencies. For that table I used the knp_paginator:
/**
* @var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$request->query->getId('page', 1),
5
);
the $docAgencies is defined like that so it's no query, but that's the way I need to get the information!
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$docAgencies = $document->getAgencies();
When first accessing the page, everything is fine and page one of the table is being shown, but as soon as I try to click on another page of the table I get an error:
Controller "DocumentBundle\Controller\Document\EditController::editAction()" requires that you provide a value for the "$id" argument (because there is no default value or because there is a non optional argument after this one).
and my route looks like this:
http://localhost/sp/web/app_dev.php/document/document/edit?page=3
so the id of the document was just deleted and there's nothing to be accessed. I tried to add a /{page} to my route like it was recommended in other Stackoverflow questions but this doesn't seem to work for me either. That's how I tried it:
* @Route("/document/edit/{id}/{pag}", name="documentBundle_edit", requirements={"id" = "\d+", "pag" = "\d+"}, defaults={"id" = 0, "pag":1})
the editAction:
public function editAction(Request $request, $id, $pag) {
..
and within the paginate function:
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$pag,
5
);
any ideas why this is not working?
update twig view
{% block content %}
{{ form_start(form) }}
<div class="row">
{% include 'Form/form_errors_banner.html.twig' %}
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'header.info'|trans }}</legend>
{% include 'DocumentBundle:Panels:DocumentInfo.html.twig' %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.comments'|trans }}</legend>
{% include 'AppBundle::CommentTable.html.twig' with {
'entity': document,
'add_comments': true
} %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.distribution'|trans }}</legend>
<div id="upload_profile_no">
{% trans_default_domain 'AppBundle' %}
{# CONFIG #}
{% if deleteButton is not defined %}
{% set deleteButton = true %}
{% endif %}
{{ form_label(form.agencies) }}<br>
{{ form_widget(form.agencies) }} <br> <br>
<table class="footable">
{# header fields #}
<thead>
<tr>
<th data-field="iata">{{ 'label.iata'|trans }}</th>
<th data-field="name">{{ 'label.name'|trans }}</th>
<th data-field="city">{{ 'label.city'|trans }}</th>
<th data-field="country">{{ 'label.country'|trans }}</th>
{% if deleteButton %}<th data-field="delete"></th>{% endif %}
</tr>
</thead>
{% block tablebody %}
{# body fields #}
<tbody>
{% for agency in docAgencies %}
<tr>
<td data-title="iata" data-market="{{ agency.market.id }}"><a href="{{ path('appBundle_agencyEdit', {'id': agency.id}) }}">{{ agency.id }}</a></td>
<td data-title="name">{{ agency.account }}</td>
<td data-title="city">{{ agency.cityName }}</td>
<td data-title="country">{{ agency.market.id }}</td>
{% if deleteButton %}
<td data-title="delete">
<button class="btn btn-danger btn-xs btn-remove-row" type="button" data-index="{{ agency.id }}">
<span class="glyphicon glyphicon-minus"></span>
</button>
<button class="btn btn-primary btn-xs btn-undo-remove hidden" type="button" data-index="{{ agency.id }}">
<span class="glyphicon glyphicon-repeat"></span>
</button>
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
{% endblock %}
</table>
{% if docAgencies.pageCount > 1 %}
<div class="navigation text-center">
{{ knp_pagination_render(docAgencies) }}
</div>
{% endif %}
</div>
<br>
<div class="row">
<div class="col-md-6">
{{ form_row(form.airlines, { 'attr': { 'class': 'form-inline'} }) }}
</div>
<div class="col-md-6">
{{ form_row(form.products, { 'attr': { 'class': 'form-inline'} }) }}
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
<legend>{{ 'label.attachments'|trans }}</legend>
{% set fileDomain = 'document' %}
{% include 'AppBundle::AttachmentConfig.html.twig' %}
{% include 'AppBundle::DisplayAttachments.html.twig' with {'entity': document} %}
{% include 'AppBundle::FileUpload.html.twig' %}
</div>
</div>
</div>
</div>
<div class="row">
{% include 'AppBundle::HelpSubmitButton.html.twig' %}
</div>
{{ form_end(form) }}
{% include 'DocumentBundle:Action/UploadProfile:modals.html.twig' %}
{% endblock content %}
the part for the pagination is the table with {% for agency in docAgencies %}
**update 2 ** my full controller:
class EditController extends Controller {
/**
* @Route("/document/edit", name="documentBundle_edit2")
* @Route("/document/edit/{id}/{pag}", name="documentBundle_edit", requirements={"id" = "\d+", "pag" = "\d+"}, defaults={"id" = 0, "pag" = 1})
* @Template()
*/
public function editAction(Request $request, $id, $pag) {
$currentuser = $this->container->get('security.token_storage')->getToken()->getUser();
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$allComments = $document->getComments();
$docAgencies = $document->getAgencies();
$statusRepository = $em->getRepository('DocumentBundle:Status');
if($this->get('security.authorization_checker')->isGranted('ROLE_DOCUMENT_EDIT') && $document->getStatus()->getName() == 'Effective' && $document->isActive()
|| $this->get('security.authorization_checker')->isGranted('ROLE_CONTRACT_ADMIN')){
/*
* GET DOCUMENT FROM DB
*/
/*
* CHECK Document
*/
if($document == null)
{
return $this->get('app.error_helper')->throwError('error.404');
}
$form = $this->createForm(DocumentEditType::class, $document);
/*
* CREATE PAGINATION FOR TABLES
*/
/**
* @var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$pag,
5
);
$agencyTable->setTemplate('DocumentBundle::table_pagination.html.twig');
$agencyTable->setUsedRoute('documentBundle_edit');
$agencyTable->setParam('id', $id);
$commentTable = $paginator->paginate(
$allComments,
$pag,
5
);
$commentTable->setTemplate('DocumentBundle::table_pagination.html.twig');
/*
* IF REQUEST IS VALID
*/
$form->handleRequest($request);
if ($form->isValid()) {
$effective = date_format($document->getEffective(), 'Y-m-d');
$expires = date_format($document->getExpires(), 'Y-m-d');
$now = date('Y-m-d');
if($now < $effective) {
$status = $statusRepository->findOneById('3');
} elseif ($now >= $expires) {
$status = $statusRepository->findOneById('2');
} else {
$status = $statusRepository->findOneById('1');
}
$document->setStatus($status);
$em->flush();
$this->addFlash(
'success',
'The document has been edited!'
);
return $this->redirectToRoute('documentBundle_document_list');
}
/*
* DISPLAY Document
*/
return $this->render('DocumentBundle:Document:edit.html.twig', Array(
'document' => $document,
'docAgencies' => $agencyTable,
'comments' => $commentTable,
'form' => $form->createView(),
));
} else {
/*
* THROW ERROR
* If the acting user is not allowed to perform this action
*/
return $this->redirectToRoute('documentBundle_view_document', array(
'id' => $id
));
}
}
}
table_pagination.html.twig
<nav>
<ul class="pagination">
{# Previous #}
{% if startPage == 1 %}
<li class="disabled">
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(app.request.attributes.get('_route'), {'page': startPage - 1}) }} " aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{# Pages #}
{% if pageCount < 12 %}{# less than 12 Pages #}
{% for i in 1..pageCount %}
<li {% if startPage == i %}class="active"{% endif %}><a href="{{ path(app.request.attributes.get('_route'), {'page': i}) }} ">{{i}}</a></li>
{% endfor %}
{% else %}
{% if startPage < 8 %}{# any current page before 7 #}
{# Pages #}
{% for i in 1..8 %}
<li {% if startPage == i %}class="active"{% endif %}><a href="{{ path(app.request.attributes.get('_route'), {'page': i}) }} ">{{i}}</a></li>
{% endfor %}
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': pageCount - 1}) }} ">{{pageCount - 1}}</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': pageCount}) }} ">{{pageCount}}</a></li>
{% else %}
{% if startPage > pageCount - 7 %}{# any current page in the last 7 #}
{# Pages #}
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': 1}) }} ">1</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': 2}) }} ">2</a></li>
<li class="disabled"><a href="#">...</a></li>
{% for i in 7..0 %}
<li {% if startPage == pageCount - i %}class="active"{% endif %}><a href="{{ path(app.request.attributes.get('_route'), {'page': pageCount - i}) }} ">{{pageCount - i}}</a></li>
{% endfor %}
{% else %}{# any other Page #}
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': 1}) }} ">1</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': 2}) }} ">2</a></li>
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': startPage - 2}) }} ">{{startPage - 2}}</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': startPage - 1}) }} ">{{startPage - 1}}</a></li>
<li class="active"><a href="{{ path(app.request.attributes.get('_route'), {'page': startPage}) }} ">{{startPage}}</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': startPage + 1}) }} ">{{startPage + 1}}</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': startPage + 2}) }} ">{{startPage + 2}}</a></li>
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': pageCount - 1}) }} ">{{pageCount - 1}}</a></li>
<li><a href="{{ path(app.request.attributes.get('_route'), {'page': pageCount}) }} ">{{pageCount}}</a></li>
{% endif %}{# any current page in the last 7 #}
{% endif %}{# any current page before 8 #}
{% endif %}{# less than 12 Pages #}
{# Next #}
{% if startPage == pageCount %}
<li class="disabled">
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(app.request.attributes.get('_route'), {'page': startPage + 1}) }} " aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
**update including @ste 's help ** Edit Controller:
* @Route("/document/edit/{id}/{page}", name="documentBundle_edit", requirements={"id" = "\d+", "page" = "\d+"}, defaults={"page" = 1})
* @Template()
*/
public function editAction(Request $request, $id, $page) {
$em = $this->getDoctrine()->getManager();
$document = $em->getRepository('DocumentBundle:Document')->findOneByIdInContext($id, $currentuser);
$allComments = $document->getComments();
$docAgencies = $document->getAgencies();
/*
* CREATE PAGINATION FOR TABLES
*/
/**
* @var $paginator \Knp\Component\Pager\Paginator
*/
$paginator = $this->get('knp_paginator');
$agencyTable = $paginator->paginate(
$docAgencies,
$page,
5
);
$agencyTable->setTemplate('DocumentBundle::table_pagination.html.twig');
$commentTable = $paginator->paginate(
$allComments,
$page,
5
);
$commentTable->setTemplate('DocumentBundle::table_pagination.html.twig');
return $this->render('DocumentBundle:Document:edit.html.twig', Array(
'document' => $document,
'docAgencies' => $agencyTable,
'comments' => $commentTable,
'form' => $form->createView(),
));
}
the pagination template
{# Pagination to be included anywhere. Needs {page, pageCount} #}
<nav>
<ul class="pagination">
{# Previous #}
{% if startPage == 1 %}
<li class="disabled">
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(route, query|merge({'page': startPage - 1})) }} " aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %}
{# Pages #}
{% if pageCount < 12 %}{# less than 12 Pages #}
{% for i in 1..pageCount %}
<li {% if startPage == i %}class="active"{% endif %}><a href="{{ path(route, query|merge({'page': i})) }} ">{{i}}</a></li>
{% endfor %}
{% else %}
{% if startPage < 8 %}{# any current page before 7 #}
{# Pages #}
{% for i in 1..8 %}
<li {% if startPage == i %}class="active"{% endif %}><a href="{{ path(route, query|merge({'page': i})) }}">{{i}}</a></li>
{% endfor %}
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(route, query|merge({'page': pageCount - 1})) }}">{{pageCount - 1}}</a></li>
<li><a href="{{ path(route, query|merge({'page': pageCount})) }}">{{pageCount}}</a></li>
{% else %}
{% if startPage > pageCount - 7 %}{# any current page in the last 7 #}
{# Pages #}
<li><a href="{{ path(route, query|merge({'page': 1})) }} ">1</a></li>
<li><a href="{{ path(route, query|merge({'page': 2})) }} ">2</a></li>
<li class="disabled"><a href="#">...</a></li>
{% for i in 7..0 %}
<li {% if startPage == pageCount - i %}class="active"{% endif %}><a href="{{ path(route, query|merge({'page': pageCount - i})) }} ">{{pageCount - i}}</a></li>
{% endfor %}
{% else %}{# any other Page #}
<li><a href="{{ path(route, query|merge({'page': 1})) }}">1</a></li>
<li><a href="{{ path(route, query|merge({'page': 2})) }}">2</a></li>
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(route, query|merge({'page': startPage - 2})) }} ">{{startPage - 2}}</a></li>
<li><a href="{{ path(route, query|merge({'page': startPage - 1})) }} ">{{startPage - 1}}</a></li>
<li class="active"><a href="{{ path(route, query|merge({'page': startPage})) }} ">{{startPage}}</a></li>
<li><a href="{{ path(route, query|merge({'page': startPage + 1})) }}">{{startPage + 1}}</a></li>
<li><a href="{{ path(route, query|merge({'page': startPage + 2})) }} ">{{startPage + 2}}</a></li>
<li class="disabled"><a href="#">...</a></li>
<li><a href="{{ path(route, query|merge({'page': pageCount - 1})) }} ">{{pageCount - 1}}</a></li>
<li><a href="{{ path(route, query|merge({'page': pageCount})) }} ">{{pageCount}}</a></li>
{% endif %}{# any current page in the last 7 #}
{% endif %}{# any current page before 8 #}
{% endif %}{# less than 12 Pages #}
{# Next #}
{% if startPage == pageCount %}
<li class="disabled">
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% else %}
<li>
<a href="{{ path(route, query|merge({'page': startPage + 1})) }} " aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
and this is how I add the pagination to my template:
{{ knp_pagination_render(docAgencies) }}
It seems that you have a problem in table_pagination.html.twig
.
You should replace this:
{{ path(app.request.attributes.get('_route'), {'page': THE_PAGE_YOU_HAVE}) }}
with this:
{{ path(route, query|merge({'pag': THE_PAGE_YOU_HAVE})) }}
or this
{{ path(app.request.attributes.get('_route'), app.request.query.all|merge({'pag': THE_PAGE_YOU_HAVE})) }}
Let me know if it works.
Further, you should remove the default value for id
in your route for editAction