LoginSignup
11
7

More than 5 years have passed since last update.

MW WP Formで動的にプルダウンの項目を変更する

Last updated at Posted at 2017-08-17

24歳、習作です。
MW WP Formを使って記事タイトルのようなことをやりたかったのですが、ググってもそれっぽい記事がなかったので自分で組んでみました。

概要

hoge.png

要するにこういうやつです。
それぞれの項目はカスタム投稿で管理し、希望コース名は投稿タイトル、希望日時はカスタムフィールドで入力するとします。

なお、カスタムフィールドは自由に項目数を増減できるようにWPAlchemyのRepeating Field Groupsを使用しています。
参考:WPAlchemy MetaBox PHP Class#Repeating Field Groups

※Advanced Custom FieldsのRepeater Fieldアドオンでもできると思います

大まかな流れ

希望コースのプルダウンを変更する
 ↓
変更後の値を取得し、AjaxでAPIにリクエストして希望日時の一覧を取得する
 ↓
取得した希望日時の一覧をjQueryでプルダウンにセットする

前提条件

カスタム投稿名
course
カスタムフィールドグループ名
variable_date
希望日時のカスタムフィールド名
date

以上の条件でカスタム投稿およびカスタムフィールドを定義しているものとします。

コード

フォーム
<dl>
    <dt><label for="course">希望コース</label></dt>
    <dd>[mwform_select name="course_name" id="course"]</dd>
    <dt><label for="date">希望日時</label></dt>
    <dd>[mwform_select name="course_date" id="date"]</dd>
</dl>

通常通り、MW WP Formの記法でプルダウンの項目を作成します。
なお、プルダウンの値はフィルターフックを使って挿入するのでフォーム側のコードでは入力しません。

functions.php
/**
 * フォームのプルダウンの値を出力する
 * @param   array   $children   select配下のoption値
 * @return  array   $atts   フォームの要素
 */
function set_select_children($children, $atts){
    // カスタム投稿名courseの投稿を全て取得し、各投稿のタイトルを希望コースのプルダウンの値として挿入する
    if($atts['name'] == 'course_name'){
        $args = array(
            'post_type' => 'course',
            'posts_per_page' => -1,
            'post_status' => 'publish'
        );
        $posts = get_posts($args);
        foreach($posts as $post){
            $children[$post->post_title] = $post->post_title;
        }
    }
    // カスタム投稿名courseの投稿を全て取得し、かつ各投稿のカスタムフィールドを全て取得した上で
    // 希望日時のプルダウンの値として挿入する
    elseif($atts['name'] == 'course_date'){
        $args = array(
            'post_type' => 'course',
            'posts_per_page' => -1,
            'post_status' => 'publish'
        );
        $posts = get_posts($args);
        foreach($posts as $post){
            $dates = get_post_meta($post->ID, 'variable_date', true);
            foreach($dates as $date){
                $children[$date['date']] = $date['date'];
            }
        }
    }
    return $children;
}
add_filter('mwform_choices_mw-wp-form-xxx', 'set_select_children', 10, 2);

functions.phpに、MW WP Formのmwform_choices_mw-wp-formのフィルターフックを使用して各プルダウンに値をセットする関数を記載します。
参考:mwform_choices_mw-wp-form-xxx | MW WP Form

api.php
require_once('../../../wp-load.php');

$args = array(
    'post_type' => 'course',
    'posts_per_page' => -1,
    'post_status' => 'publish',
    's' => $_POST['course'],
    'exact' => true
);
$post = reset(get_posts($args));

$dates = get_post_meta($post->ID, 'variable_date', true);
foreach($dates as $date){
    $return_data[] = $date['date'];
}
$return_data = json_encode($return_data);

echo $return_data;

テーマフォルダ直下にAjax用のAPIを作成します。
postされた値をカスタム投稿名courseの投稿一覧から検索し、該当する投稿のカスタムフィールドから値を取得して配列に格納し、JSON形式で値を返します。

※このへんはWordPressのREST APIを使用すればわざわざファイルを作る必要はないかもしれません

form.js
(function($){
    $(function(){
        set_date_value();

        $('#course').change(function(){
            set_date_value();
        });
    });

    function set_date_value(){
        $.ajax({
            url: '/wp-content/themes/theme_name/api.php',
            type: 'post',
            dataType: 'json',
            data: {
                course: $('#course').val()
            }
        })
        .done(function(response){
            var date = $('#date').val(),
                selected_val = null;

            $('#date').children().remove();
            $.each(response, function(index, value){
                $('#date').append($("<option>").val(value).text(value));
                if(value == date){
                    selected_val = value;
                }
            });
            if(selected_val == null){
                selected_val = $('#date option:eq(0)').val();
            }
            $('#date').val(selected_val);
        })
        .fail(function(){
            alert('エラーが発生しました。');
        });
    }
})(jQuery);

フォームのページで読み込むJavaScriptファイルです。
テーマフォルダ直下のapi.phpにAjaxを使用してpostを行い、値が返ってきたら希望日時のプルダウンの中身を空にした上で返ってきた値をセットします。

終わりに

かなり場当たり的なコードなので正直スマートなやり方ではないなあと自分でも思うのですが、参考までに。
バリデーションやプルダウンの最初の項目を「選択してください」的なものにすることはあまり考慮していませんが、そちらは別途検証したいと思います。

11
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7