WordPressのカスタムフィールドで繰り返されるデータを、Ajaxを使った非同期で取得する方法について解説しています。
繰り返し表示したいフィールドデータの数は多いが、ページ遷移をさせたくない時などに役立つ内容です。
カスタムフィールドを非同期で取得して表示した例
今回のやりたいことはこちらです。
「もっと見る」のボタンを押すと、追加でデータが5件づつ表示される仕組みです。
ソースコードを見ていただくとわかりますが、CSSのdisplay: none;で予め要素を非表示にしておいて、ボタンを押すと表示している実装ではありません。非同期でカスタムフィールドの情報を取得し、tableの最終行に要素を追加しています。
仕様は以下の通りです。
- 繰り返しフィールドのデータセットが予め5件表示されている。
- ボタンをクリックする毎に5件ずつデータが表に追加される
- 全てのデータが表に追加されたら、ボタンが非表示となる。
実装の流れは次の通りです。
- プラグインの設定を行う(Smart Custom Fields)
- テンプレートにベースとなるコードを書く(page.phpなど)
- リクエスト送信先のパスを指定する(functions.php)
- 呼び出す関数を定義する(functions.php)
- JavaScriptの処理を記述する(script.jsなど)
- CSSで見た目を調整する(style.cssなど)
順番にコードを示し解説していきます。
Smart Custom Fieldsの設定
無料で繰り返しフィールドを使える、Smart Custom Fieldsの設定をしていきます。フィールドの設定内容は以下の通りです。
- フィールド名:国と首都
- 繰り返し:オン
- グループ名:country_list
サブフィールドの設定内容は次の通りです。2つのフィールドを用意しています。
【サブフィールド その1】
- タイプ:テキスト
- ラベル:国名
- 名前:country_name
【サブフィールド その2】
- タイプ:テキスト
- ラベル:首都
- 名前:capital_name
今回はSmart Custom Fieldsを使用しましたが、Advanced Custom Fieldsでももちろん実装可能です。
Smart Custom Fieldsの開発者が下記ツイートで、今後SCFはクローズに向けて動き出すとのことを発信されています。これから制作するWebサイトへの新規導入は見送った方が良いかもしれません。
とりあえず、Smart Custom Fields と MW WP Form はクローズに向けて動こうと思います。どちらも公式ディレクトリでのユーザー数が一定を超えていて自分ではクローズできないということみたいなので、ちょっといついつにクローズしますと名言はできませんが、一応そういう方向性でいこうと思います。
— キタジマタカシ🐒Snow Monkey/unitone開発者 (@inc2734) September 9, 2023
テンプレートへの記載内容
page.php等のテンプレートに以下のコードを記述します
<?php
$list_items = SCF::get('country_list');
$count = 0;
?>
<table class="js-table">
<tr>
<th class="th">国名</th>
<th class="th">首都</th>
</tr>
<?php foreach ($list_items as $list_item) : ?>
<?php if ($count < 5) : ?>
<tr>
<th><?php echo $list_item['country_name']; ?></th>
<td><?php echo $list_item['capital_name']; ?></td>
</tr>
<?php $count++; ?>
<?php endif; ?>
<?php endforeach; ?>
</table>
<div class="btn">
<button id="ajax_demo_submit" class="js-btn">もっと見る</button>
</div
初期値として5件表示させたいので、条件分岐で$count < 5
としています。
リクエスト送信先のパスを指定
functions.php
において、Ajaxを利用する際のリクエスト送信先のURLをグローバル変数として定義しておきます。
<?php
function add_my_ajaxurl() {
?>
<script>
const ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
</script>
<?php
}
add_action( 'wp_head', 'add_my_ajaxurl', 1 );
WordPressを利用した環境でAjaxを使うには、/wp-admin/admin-ajax.php にリクエストを送信することが必要です。
呼び出す関数を定義
次にリクエストが送信された際に、実行する処理の内容をこちらもfunctions.php
に記述します。
function ajax_get_new_fields() {
$returnObj = array();
// Smart Custom Fieldのデータを取得。「7」はカスタムフィールドを表示している固定ページのID
$list_items = SCF::get('country_list', 7);
// 6件目以降のデータを取得
for ($i = 5; $i < count($list_items); $i++) {
$list_item = $list_items[$i];
$returnObj[] = array(
'country_name' => $list_item['country_name'],
'capital_name' => $list_item['capital_name'],
);
}
//JSON形式の文字列で返す
echo json_encode($returnObj);
die();
}
add_action('wp_ajax_ajax_get_new_fields', 'ajax_get_new_fields');
add_action('wp_ajax_nopriv_ajax_get_new_fields', 'ajax_get_new_fields');
- 6件目以降のデータを取得したいので、for文の初期値は
$i = 5;
としています。 SCF::get
の第二引数には、カスタムフィールドを表示しているページのページIDを入れます。
JavaScriptの処理を記述
次にscript.js
などのJSファイルに以下のコードを記述します。
document.addEventListener('DOMContentLoaded', function () {
const xhr = new XMLHttpRequest();
xhr.open('POST', ajaxurl);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
if (xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
const jsonData = response;
const submit = document.querySelector('#ajax_demo_submit')
let currentIndex = 0;
submit.addEventListener('click', function () {
const table = document.querySelector('.js-table');
const dataToShow = jsonData.slice(currentIndex, currentIndex + 5);
currentIndex += 5;
dataToShow.forEach(function (val) {
const newRow = document.createElement('tr');
newRow.classList.add('added-row');
newRow.innerHTML = `<th>${val.country_name}</th><td>${val.capital_name}</td>`;
table.appendChild(newRow);
setTimeout(function () {
newRow.classList.add('is-show');
}, 100);
});
if (currentIndex >= jsonData.length) {
submit.classList.add('is-hidden');
}
});
}
};
xhr.send('action=ajax_get_new_fields');
});
jQueryで同じコードを記述すると、次のようになります。
$(function () {
$.ajax({
type: 'POST',
url: ajaxurl,
data: {
'action': 'ajax_get_new_fields',
},
success: function (response) {
jsonData = JSON.parse(response);
}
});
// 現在表示しているデータのインデックス
let currentIndex = 0;
$('#ajax_demo_submit').on('click', function () {
const table = document.querySelector('.js-table');
// 残りのデータから5件ずつ取得
const dataToShow = jsonData.slice(currentIndex, currentIndex + 5);
currentIndex += 5;
// 取得したデータを表示
dataToShow.forEach((val) => {
const newRow = document.createElement('tr');
newRow.classList.add('added-row');
newRow.innerHTML = `
<th>${val.country_name}</th>
<td>${val.capital_name}</td>
`;
table.appendChild(newRow);
// setTimeoutを使用してアニメーションのトリガーを遅延
setTimeout(function () {
$(newRow).addClass('is-show');
}, 100);
});
// カスタムフィールドのデータがすべて表示された場合はボタンを非表示に
if (currentIndex >= jsonData.length) {
$('#ajax_demo_submit').addClass('is-hidden')
}
});
});
処理内容をざっくりと説明すると、サーバーにリクエストを送信し、サーバーから受け取ったデータを5件ずつテーブルに追加しています。
ajax_get_new_fieldsアクションを実行することで、サーバー側でデータの取得と処理が行われることを想定しています。
CSSを追加する
最後に見た目調整用のCSSを追加します。
※テーブルタグに関する基本的な記述は省いて、アニメーションに関するコードのみ抜粋しています。
.added-row {
opacity: 0;
transition: opacity 1s;
}
.added-row.is-show {
opacity: 1;
}
.btn button.is-hidden {
opacity: 0;
transition: opacity 1s;
}
サーバーから受け取ったデータであるtr
タグ(クラス:added-row
)は、最初は透明の状態で、is-show
のクラスがつくと不透明度が100%となります。
またbuttton
タグは、全てのデータが表示されるとis-hidden
クラスが付与され、透明となります。