WordPress|繰り返しフィールドのデータを非同期で取得して表示する方法

繰り返しフィールドを非同期で取得して表示する方法

WordPressのカスタムフィールドで繰り返されるデータを、Ajaxを使った非同期で取得する方法について解説しています。

繰り返し表示したいフィールドデータの数は多いが、ページ遷移をさせたくない時などに役立つ内容です。

目次

カスタムフィールドを非同期で取得して表示した例

今回のやりたいことはこちらです。

「もっと見る」のボタンを押すと、追加でデータが5件づつ表示される仕組みです。

ソースコードを見ていただくとわかりますが、CSSのdisplay: none;で予め要素を非表示にしておいて、ボタンを押すと表示している実装ではありません。非同期でカスタムフィールドの情報を取得し、tableの最終行に要素を追加しています。

仕様は以下の通りです。

仕様
  • 繰り返しフィールドのデータセットが予め5件表示されている。
  • ボタンをクリックする毎に5件ずつデータが表に追加される
  • 全てのデータが表に追加されたら、ボタンが非表示となる。

実装の流れは次の通りです。

  1. プラグインの設定を行う(Smart Custom Fields)
  2. テンプレートにベースとなるコードを書く(page.phpなど)
  3. リクエスト送信先のパスを指定する(functions.php)
  4. 呼び出す関数を定義する(functions.php)
  5. JavaScriptの処理を記述する(script.jsなど)
  6. 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に関する注意点

Smart Custom Fieldsの開発者が下記ツイートで、今後SCFはクローズに向けて動き出すとのことを発信されています。これから制作するWebサイトへの新規導入は見送った方が良いかもしれません。

テンプレートへの記載内容

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クラスが付与され、透明となります。

目次