getgrav / grav-plugin-pagination

Grav Pagination Plugin
https://getgrav.org
MIT License
27 stars 20 forks source link

"pagination" variable in "pagination.html.twig" doesn't containt the right data. #31

Open KennethJoris opened 6 years ago

KennethJoris commented 6 years ago

On a twig template i use the 'Collection Object Methods' to difine a collection like it states in the GRAV documentation:

{% set collection = page.collection({
         'items': '@self.children', 
         'pagination': true, 
         'order': {'by': 'title'}, 
         'limit': 1}) 
%}

I pass this data to the plugin 'pagination.html.twig' template.

{% if config.plugins.pagination.enabled and collection.params.pagination %}
    {% include 'partials/pagination.html.twig' with {'base_url':page.url, 'pagination':collection.params.pagination} %}
{% endif %}

Here i have my issue:

In the plugin template '' the first condition will therefore always return false.

{% set pagination = pagination|default(page.collection.params.pagination) %}
{% if pagination|length > 1 %} ... {% endif %}

Looking inside the plugin template its unclear to me what correct data is expected. And how to pass this through?

KennethJoris commented 6 years ago

I made a small twig pagination that works with the Grav Collection Methods:

Example:

       {% set collection = page.collection({
        'items': '@self.children', 
        'pagination': true, 
        'order': {'by': 'title'}, 
        'limit': 2}) 
    %}

    {% set itemsInCollection = page.collection({'items': collection.params.items})|length %}
    {% set itemsPerPage = collection.params.limit %}
    {% set pagesInCollection = (itemsInCollection / itemsPerPage)|round(0, 'ceil') %}
    {% set currentPage = uri.param('page')|default('1') %}

    <ul class="pagination">
    {% for i in range(1, pagesInCollection) %}
        <li {% if currentPage is same as('' ~ i ~ '') %} class="currentpage" {% endif %}>
            <a href="{{ page.url ~ '/page' ~ system.param_sep ~ i }}">{{ i }}</a>
        </li>
    {% endfor %}
    </ul>

    {# Render the list of blog posts (automatically filtered when using pagination) #}
    {% for child in collection %}
       {{ child.title }} <br>
    {% endfor %}
ghost commented 6 years ago

This problem takes a lot of my time at the moment. When I look inside the grav-skeleton-blog-site the pagination param is a \Grav\Plugin\PaginationHelper, in the flow of my templates it is only a boolean = true. I tried calls like do paginate( collection, limit ) like described in the README. This should do the magic, it calls paginateCollection in grav-plugin-pagination/pagination.php, which overwrites the pagination param with a \Grav\Plugin\PaginationHelper and slices the collection. The call does not work for me at the moment, I will investigate more. It is rather confusing, that a parameter is changed to another type and meaning, why not use another name?

Also I don't know where it is done in the blog skeleton. Any advice appreciated.

ghost commented 6 years ago

I think I found the reason. In the grav-skeleton-blog-site the preparation of the collection is done by the onCollectionProcessed-event, but, as I suppose, only for the default collection, not for another defined collection.

So the call to do paginate() is essential, but really not working. The reason is: the version 1.3.2 installed by bin/gpm install pagination is different from the version 1.3.2 installed by the zip. The twig folder is missing and the onTwigExtensions-event not registered. Also blueprints.yaml, README.md and other files are different.

When I install from ZIP, do paginate() does it's job.

grantholle commented 6 years ago

I'm having the same problem using v1.4.1. I tried installing using gpm and zip (which was the same version).

The collection.params.pagination never gets the "magic", just remains true.

grantholle commented 6 years ago

I figured out my proglem. I was including limit in my collection() call.

If I exclude the limit from my collection parameters and only pass what my limit is do the do paginate(collection, limit) it works as expected.

azamatg commented 5 years ago

If I exclude the limit from my collection parameters and only pass what my limit is do the do paginate(collection, limit) it works as expected.

can you explain this please?

I cannot find the way to get this strange unusable plugin work

Heraes-git commented 5 years ago

I have exactly the same problem as @Genenenenaam and tried the do paginate( collection, limit ) as @tremel did : but I have a blank paginator, in raw HTML, without pages to paginate.

2019-04-21_17h30m45s_chrome

I tried again with excluding the limit: from the frontmatter as @grantholle suggested, and this time, I have a Crikey error :

2019-04-21_17h25m21s_chrome

So it seems that the plugin is totally broken (no rendering + no CSS loaded in the assets in the <head>).

numito commented 5 years ago

Hello,

There is an issue with the pagination plugin, if you have a collection to has less items than the limit, you get empty pagination instead of not getting a paginator at all. The reason is the pagination variable is initialized to true, and then never changed to an empty array. There the pagination|length gives 4 because it counts the number of letters in the word true instead of counting an empty array.

There are 2 ways to fix this issue on line 124 of file pagination.php. Solution 1: set the pagination variable to an empty array instead of true $collection->setParams(['paginationEnabled' => array()]); Solution 2: don't set the pagination variable unless there is enough item and instead to show there is pagination activated but not enough item to paginate set a variable called paginationEnabled to true. $collection->setParams(['paginationEnabled' => 'true']);

Solution 1 makes has my preference.

Regards, Numa

rhukster commented 5 years ago

How about a pull request?

Heraes-git commented 5 years ago

Hi, I come back here to give more infos on what I discovered about the bugs. I'm not familiar with GIT pushes, and anyway I didn't find any PHP fixes, so it's pure workaround and good practice here :+1: . I just dump that, as a memo for further documentation edition.

Summary :

1 - How to use the plugin correctly (conflict) 2 - Excerpt of a full template processing 3 - The problem with modular pages 4 - Insights of the PHP, for possible fixes

1 - How to use the plugin correctly (conflict)

In short : there's two way of calling the plugin in a page, and we can't use both or it will conflicts !

Reminder

The plugin necessitate two things :

And it allows one thing :

First method

  1. We declare all necessary option in the frontmatter, wich are composed of only two :
    content:
    pagination: true
    limit: [integer]
  2. We do NOT use a {% do paginate() %}.

Second method

  1. We declare one option in the frontmatter, the most essential one :
    content:
    pagination: true
  2. We do NOT use a limit: field.
  3. We use {% do paginate() %}.

2 - Excerpt of a full template processing

{# *** Collection preprocessing *** #}
{% if page.collection %}
    {% set collection = page.collection() %}
    {% set limit = page.header.content.limit ?: '5' %}
{% else %}
    {% set limit = '5' %}
    {% set collection_options = { items: {'@page.children': page.url}, 'limit': limit, 'order': {'by': 'date', 'dir': 'desc'}, 'pagination': true } %}
    {% set collection = page.collection(collection_options) %}
{% endif %}
{# *** /Collection preprocessing *** #}
{% if config.plugins.pagination.enabled and collection.params.pagination and not page.header.content.limit %}
    {% do paginate(collection, limit) %}
{% endif %}

{% for item in collection %}
... Things to display the items...
{% endfor %}

{% if config.plugins.pagination.enabled and collection.params.pagination %}
        {% include "partials/pagination.html.twig" with {'base_url':page.url, 'pagination':collection.params.pagination} %}
{% endif %}

3 - Problem with modular pages, and workaround

Modular page are rendered differently, and some things can be impossible to reach in the PHP during the events.

So, because of this, the presence of a frontmatter pagination field is just checked during the WHOLE page processing _( meaning, the parent page that a modular can have !) but not during the processing of the modular_ sub-page. Consequently, the pagination plugin doesn't find the frontmatter field, and doesn't load the CSS wich results in a raw <ul> !

So as a solution, just load manually the asset in your template that extends the base.html.twig, by rewritting any {% block %} that would have been created (or that you can create) around the assets.css() in the header of the base.html.twig.

{% block assets %}
  {{ parent() }}
  {% do assets.addCss('plugin://pagination/css/pagination.css') %}
{% endblock %}

Or directly in the base.html.twig, add inside the header :

{% if page.route == "/your_page" %}
  {% do assets.addCss('plugin://pagination/css/pagination.css', {'group':'workaround'}) %}
{% endif %}
{{ assets.css('workaround') }}

I've conditioned it to a route, and assigned it to a group for more control, but that's totally optional.

Heraes-git commented 5 years ago

4 - Insights of the PHP, for possible fixes

But I don't understand why it would make the plugin to bug. :thinking:

Anyway, it is clearly here, at this moment when the _pagecount is done, that the plugin fails if we have a set a limit: field in the frontmatter !

I tried to set an integer, or between quotes ' '; but nothing works.