Make something appear on page 1 only

So I am paginating my blog as per the kirby way. I want featured items to appear at the top.

Currently in my controller I have just done:

$featured = $sorted->limit(3);
$note = $sorted->not($featured)->paginate(3);

So you can see that from my collection I am getting the first 3 (sorted by date) and then excluding those 3 from the rest of the collection.

I only want the featured items to appear on page one. How would I do this?

But that would happen automatically if you paginate your $sorted collection. Why the two collections? With paginate(3) you get 3 items per page, so the first 3 would be on the first page.

Moving the paginate to my sorted doesn’t achieve what I want, because a featured block still shows up on page 2.

Example bellow, the HTML comments say what I want to achieve.

Template

<!-- ONLY SHOW THIS BLOCK ON PAGE ONE -->
<?php if ($featured->count()): ?>
    <div class="o-featured">
        <?php foreach ($featured as $item): ?>
            <article class="o-featured__article">
            </article>
        <?php endforeach ?>
    </div>
<?php endif ?>

<!-- THIS IS THE NORMAL ARTICLE LIST WHICH IS PAGINATED -->
<?php if ($note->count()): ?>
    <div class="o-note">
        <?php foreach ($note as $item): ?>
            <article class="o-note__article">
            </article>
        <?php endforeach ?>
    </div>
    <?php snippet('pagination') ?>
<?php else: ?>
    <div class="o-noresults">
        <h3 class="o-noresults__title"><?= t('nonotestitle') ?></h3>
        <p class="o-noresults__text"><?= t('nonotestext') ?></p>
    </div>
<?php endif ?>

So my attempt was using the original collection ‘sorted’, take the first items and register them under a different name ‘featured’, inject them into their own HTML block, then exclude ‘featured’ from my ‘note’ collection and paginate my ‘note’ collection like I normally would.

This is my controller

<?php

return function ($page) {

    // Notes
    $notes = $page->children()->listed();
    $sorted = $notes->sortBy('itemDate', 'desc', 'itemTime', 'desc');

    // Categories & Tags
    $categories = $notes->pluck('category', ',', true);
    $categoryurl = $page->url();

    $tags = $notes->pluck('tags', ',', true);

    if ($tag = urldecode(param('tag'))) {
        $sorted = $sorted->filterBy('tags', $tag, ',');
    }

    if ($category = urldecode(param('category'))) {
        $sorted = $sorted->filterBy('category', $category, ',');
    }

    sort($categories);

    // Pagination
    $featured = $sorted->limit(3);
    $note = $sorted->not($featured)->paginate(3);
    $pagination = $note->pagination();

    return [
        'categories' => $categories,
        'categoryurl' => $categoryurl,
        'featured' => $featured,
        'note' => $note,
        'pagination' => $pagination,
        'tags' => $tags
    ];

};

The way I achieved something similar was on my albums page where I just used a different class for the first item but only wanted that class on page one.

<?php if ($tag = urldecode(param('tag'))): ?>
    <article class="o-album">
<?php elseif ($item->indexOf($album) == 0): ?>
    <article class="o-album o-album__first">
<?php else: ?>
    <article class="o-album">
<?php endif ?>

I found this through trial and error xD No idea if it’s the best practice or not, but it works for what I needed.

Ah, now I understand what you want to achieve.

You can check for your pagination page and only display the featured block when on page one.

In your controller, define the pagination object:

$pagination = $note->pagination();

In template:

<?php if ($pagination->isFirstPage()): ?>
<!-- ONLY SHOW THIS BLOCK ON PAGE ONE -->
<?php if ($featured->count()): ?>
    <div class="o-featured">
        <?php foreach ($featured as $item): ?>
            <article class="o-featured__article">
            </article>
        <?php endforeach ?>
    </div>
<?php endif ?>
<?php endif ?>

Ah ok, easier than I thought. Thank you very much.