Last active
July 20, 2024 17:06
-
-
Save Niq1982/4d0b97915d3d0681959dc3a50986271e to your computer and use it in GitHub Desktop.
Load more to WordPress blog archive using AlpineJS and Axios
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<div class="card"> | |
<?php if ($args['link']) : ?> | |
<a href="<?php echo esc_url($args['link']); ?>" class="global-link"> | |
</a> | |
<?php endif; ?> | |
<div class="card-image"> | |
<?php wp_get_attachment_image($args['image']); ?> | |
</div> | |
<div class="card-content"> | |
<h2> | |
<?php echo esc_html($args['title']) ?> | |
</h2> | |
<p> | |
<?php echo wp_kses_post($args['subtitle']) ?> | |
</p> | |
<div class="content"> | |
<?php echo wp_kses_post($args['content']); ?> | |
</div> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
add_action('wp_enqueue_scripts', function () { | |
wp_enqueue_script('load-more', get_theme_file_uri('js/load-more.js'),filemtime(get_theme_file_path('js/load-more.js')),true); | |
wp_localize_script('load-more', 'wpApiSettings', array( | |
'root' => esc_url_raw(rest_url()), | |
'nonce' => wp_create_nonce('wp_rest'), | |
)); | |
}); | |
add_action('rest_api_init', function () { | |
register_rest_field('post', 'card', | |
[ | |
'get_callback' => function ($post) { | |
ob_start(); | |
get_template_part('template-parts/card', '', [ | |
'image' => get_post_thumbnail_id($post['id']), | |
'link' => get_permalink($post['id']), | |
'title' => get_the_title($post['id']), | |
'subtitle' => sprintf('<time datetime="%1$s">%2$s</time>', get_the_time('c', $post['id']), get_the_date(get_option('date_format'), $post['id'])), | |
'content' => get_the_sentence_excerpt(3, get_the_excerpt($post['id'])), | |
]); | |
return ob_get_clean(); | |
}, | |
] | |
); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
get_header(); | |
global $wp_query; | |
?> | |
<main class="site-main"> | |
<section class="blog"> | |
<div class="container" x-data="loadMore(<?php echo esc_attr($wp_query->post_count) ?>, 5)"> | |
<?php if (have_posts()) : ?> | |
<?php while (have_posts()) : the_post(); ?> | |
<article> | |
<?php get_template_part('template-parts/card', '', [ | |
'image' => get_post_thumbnail_id(), | |
'link' => get_permalink(), | |
'title' => get_the_title(), | |
'subtitle' => sprintf('<time datetime="%1$s">%2$s</time>', get_the_time('c'), get_the_date()), | |
'content' => get_the_sentence_excerpt(), | |
]); ?> | |
</article> | |
<?php endwhile; ?> | |
<?php endif; ?> | |
<?php if ($wp_query->post_count < $wp_query->found_posts) : ?> | |
<template x-for="post in posts"> | |
<article x-html="post.card" x-data="{ show: false }" x-init="$nextTick(() => { show = true })" x-show="show" x-transition.duration.500ms x-transition.scale.origin.top.left></article> | |
</template> | |
<button x-bind:disabled="loading" x-show="hasMore" x-on:click="loadMore" class="button">Load more</button> | |
<?php endif ?> | |
</div> | |
</section> | |
</main> | |
<?php get_footer(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import axios from 'axios'; | |
import Alpine from 'alpinejs'; | |
const apiRoot = window.wpApiSettings.root; | |
const nonce = window.wpApiSettings.nonce; | |
const api = axios.create({ | |
baseURL: `${apiRoot}wp/v2/`, | |
headers: { 'X-WP-Nonce': nonce }, | |
}); | |
Alpine.data('loadMore', (initialOffset, perPage) => { | |
return { | |
offset: initialOffset, | |
posts: [], | |
perPage, | |
hasMore: true, | |
loading: false, | |
loadMore() { | |
this.loading = true; | |
api.get('posts', { | |
params: { | |
offset: this.offset, | |
per_page: this.perPage, | |
'_fields': 'card', | |
}, | |
}) | |
.then((response) => { | |
this.handleResponse(response); | |
}) | |
.catch((error) => { | |
console.log(error); | |
}); | |
}, | |
handleResponse(response) { | |
if (!response?.data?.length) { | |
this.hasMore = false; | |
return; | |
} | |
// Put posts in the view one at a time with a delay for fancier transition | |
response.data.forEach((post, index) => { | |
setTimeout(() => { | |
this.posts.push(post); | |
this.offset += 1; | |
}, index * 100); | |
}); | |
// Show more button if there are more posts to load | |
this.hasMore = response.data.length === this.perPage; | |
this.loading = false; | |
} | |
} | |
}); | |
Alpine.start(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment