AJAX loading dynamic blog content

I’m trying to load blog content dynamically, from what I understand AJAX is the way to do this. Unfortunately my understanding of Javascript is not very good, so any help to implement what I’m trying to achieve would be greatly appreciated.

Here is what I have so far.

This is the code I have, the first div to show the list of articles and the second div is where I want the content to load when an article link is clicked from the list.

<div class="curation-contents">
  <?php foreach($site->page('blog')
                  ->children()
                  ->visible()
                  ->flip() as $article): ?>
    <?php snippet('article', array('article' => $article)) ?>
  <?php endforeach ?>
</div>

<div class="article-container">

</div>

Here is the article snippet:

  <article class="article-item">
    <a class="load" data-target="#article-container" href="<?= $article->url() ?>">
      <h3 ><?php echo html($article->title()) ?></h3>
    </a>
    <p><?php echo kirbytext($article->intro()) ?></p>
    <time><?php echo $article->date('d/m/Y') ?></time>
  </article>

Is JSON the right tried to go about creating a JSON template but I don’t know whether it’s right or whether this is this is the right way to approach my problem,

<?php

$data = [
  'title' => $page->title()->value(),
  'text'  => $page->text()->kirbytext(),
  'date' => $page->date('d/m/Y'),
  'image' => $page->coverimage()->toFile()->url()
];

echo json_encode($data);
?>

This is my AJAX call so far:

    $(function(){

  var element = $('.load');
  var url     = element.data('article') + '.json';

$('.load').on('click', function(e) {
  e.preventDefault();
  $.ajax({
    type: "GET",
    dataType: "json",
    url: '',
    data: data,
    success: function(data) {
        
    },
  });
});

Any pointers in the right direction would be welcome

Have you seen this cookbook recipe? While it’s a bit different, it should give you the overall guidelines for your use case.

If you continue to have issues, I can look into it tomorrow, it’s a bit too late now.

A couple of things:

  • your data-target uses an id, while you container uses a class
  • you try to get the url in the JavaScript from a data attribute that does not exist.
  • Your json template should contain the HTML you want to inject

I’ve managed to wrangle sometime to work on my site again. Hopefully these pictures will explain a little better for what i’m trying to achieve.

This is the home page, the user clicks on the grey tab to look at a contents list of articles from the blog

The tab opens and the contents list and articles links to the individual articles are displayed. The user can click on the induvidual article and instead of going to the page /mywebsite/blog/article-a I would like to load the content dynamically in that tab.

Which would appear like this.

I’ve tried following the cookbook recipe suggested and trying to implement into my context.

In have my html currently set up as:

<div class="curation-contents">
  <?php foreach($articles as $article): ?>
    <?php snippet('article', array('article' => $article)) ?>
  <?php endforeach ?>
</div>

<div class="article-container" data-page="<?= $site->page('blog')->children()->visible()->url() ?>">

</div>

I’m struggling to work out the logic in the controller this is what I have so far (do I need to declare title, date, text and coverimage as variables?):

<?php
 return function($site, $pages, $page) {

 $articles = $site->page('blog')->children()->visible()->flip();
 
  if(r::ajax() && get('title') && get('date') && get('text') && get('coverimage')) {
  } else {
  echo $site->page('blog')->children()->visible()->url();
  }
  return compact('articles', 'title', 'date', 'text', 'coverimage');
 };

In my json template I currently have:

<?php
$html = '';

foreach($articles as $article) {
  $html .=  snippet('article', array('article' => $article), true);
}

$data['html'] = $html;

echo json_encode($data);
?>

In javascript I currently have:

$(function(){

var element = $('.article-container');
var url     = element.data('page') + '.json';

$('.load').on('click', function(e) {
  e.preventDefault();
  $.get(url, {title: title, date: date, text: text, coverimage: coverimage} ,function(data) {
    $(page).append(element);
  });
 });
});

Any pointers in the right direction on how to achieve this would be fantastic.

I want to propose another way to make this work:
Both Smoothstate.js (jQuery) and barba.js (non-jQuery) enable page transitions via PJAX (push state ajax) calls, using just the animations you want them to.

Instead of saving Kirby pages as JSON, you can inject the part that is different from the current page into a specific container. On the plus side, this works as progressive enhancement, so users who disabled javascript just get a normal “hard refresh” page load instead of “nothing”.

Demos are included on the project pages mentioned above, most of them much like what you try to achieve. Let me know if this is helpful!

Cheers,
S1SYPHOS