Load More with AJAX

Sure. I’ll base it on the K2 example for you:

/site/templates/projects.php

<ul class="projects" data-page="<?= $page->url() ?>" data-limit="<?= $limit ?>">

  <?php foreach($projects as $project): ?>
    <?php snippet('project', compact('project')) ?>
  <?php endforeach ?>

</ul>
<button class="load-more">Load more</button>

/site/snippets/project.php

<li class="project">
  <a href="<?= $project->url() ?>" class="project-link">
    <?php if($image = $project->image()): ?>
    <img src="<?= $image->url() ?>" alt="<?= $image->alt_text()->html() ?>" />
    <?php endif ?>
    <div class="project-caption">
      <h2 class="project-title"><?= $project->title()->html() ?></h2>
    </div>
  </a>
</li>

/site/controllers/projects.php

<?php

return function($site, $pages, $page) {

  $projects = $page->children()->visible();
  $count    = $projects->count();
  $more     = false;

  $offset   = 0;
  $limit    = 2;
  $projects = $projects->limit($limit);

  return compact('offset', 'limit', 'projects', 'more');

};

/site/templates/projects.json.php

<?php

$html = '';

$projects = $page->children()->visible();
$count    = $projects->count();

$offset = intval(get('offset'));
$limit  = intval(get('limit'));

$projects = $projects->offset($offset)->limit($limit);
$more = $count > $offset + $limit;

foreach($projects as $project) {

  $html .= snippet('project', compact('project'), true);

}

$data['html'] = $html;
$data['more'] = $more;

echo json_encode($data);

/site/controllers/projects.json.php

<?php

return function ($kirby, $site, $pages, $page) {
  
  $projects = $page->children()->visible();
  $count    = $projects->count();

  $offset = intval(get('offset'));
  $limit  = intval(get('limit'));

  $projects = $projects->offset($offset)->limit($limit);

  $more = $count > $offset + $limit;

  return [
      compact('offset', 'limit', 'projects', 'more')
    ];
};

JS

$(function () {
  var element = $(".projects");
  var url = element.data("page") + ".json";
  var limit = parseInt(element.data("limit"));
  var offset = limit;

  $(".load-more").on("click", function (e) {
    $.get(url, { limit: limit, offset: offset }, function (data) {
      if (data.more === false) {
        $(".load-more").hide();
      }

      element.children().last().after(data.html);

      offset += limit;
    });
  });
});

This should work. Let me know if you have any problems!

2 Likes