WordPressの検索フォームに「ラジオボタンの選択肢に応じて、セレクトボックスの中身が変わる」機能を実装した。
こんなやつ↓↓
ラジオボタンを選ぶと、セレクトボックスの中身が変わっているのがわかると思う。
今回はこれを実装する。javascript(jQuery)で機能を実現する。
想定条件
下記の条件の検索フォームを作成する。
- 検索する対象:カスタム投稿「article」
- 検索に使用するもの:カスタムタクソノミー「目的 purpose」 or カスタムタクソノミー「カテゴリー article-cat」
- 仕組み:目的別検索 or カテゴリー検索 を選択できる。どちらかを選択すると、選択肢に応じて選択肢が変化する。
今回はカスタム投稿・カスタムタクソノミーを利用するが、通常投稿・通常カテゴリー・タグでもほぼ同様の方法で実装できます。
結論
searchform.phpに下記を記述。
(基本的なWordPress検索フォームの作り方をベースに作っているので、基本的な部分はあまり解説しない。「そもそもsearchform.phpってなに?」って人は、他の方のブログで色々包括的に説明されているので参照にされたし)
<form action="<?php echo esc_url(home_url('/')); ?>" method="get">
<table>
<tr class="parent-tr">
<th>
<div class="th-inner">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/search.svg" alt="検索">検索項目
</div>
</th>
<td>
<label>
<input name="parent" type="radio" value="目的別" checked>
目的別
</label>
<label>
<input name="parent" type="radio" value="カテゴリー別">
カテゴリー別
</label>
</td>
</tr>
<tr class="keyword-tr">
<th>
<div class="th-inner">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/genre.svg" alt="ジャンル">ジャンルを探す
</div>
</th>
<td>
<div class="select-wrapper">
<select name="purpose" id="search-select" class="postform">
<option value="指定しない">指定しない</option>
<?php
$terms = get_terms('purpose',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo "<option class='level-0' value='$term->slug'>$term->name</option>";
}
?>
</select>
<div class="select-btn">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/bottom-arrow.svg" alt="arrow">
</div>
</div>
</td>
</tr>
</table>
<input type="hidden" name="post_type" value="article">
<input type="hidden" name="s">
<button class="submit-btn" type="submit">
この条件で探す
</button>
</form>
<script>
let purpose = {
<?php
$terms = get_terms('purpose',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo $term->slug.":'".$term->name."',";
}
?>
}
let category = {
<?php
$terms = get_terms('article-cat',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo $term->slug.":'".$term->name."',";
}
?>
}
jQuery('input[name="parent"]:radio').change(function(){
let parent = jQuery(this).val();
if(parent == '目的別') {
searchOption(purpose);
jQuery('#search-select').attr('name','purpose');
} else {
searchOption(category);
jQuery('#search-select').attr('name','article-cat');
}
})
function searchOption(n) {
jQuery('#search-select option').remove();
jQuery('#search-select').append('<option class="level-0" value>指定しない</option>');
jQuery.each(n, function(property,value){
jQuery('#search-select').append('<option class="level-0" value=' + property + '>' + value + '</option>');
})
}
</script>
解説① フォーム部分
<form action="<?php echo esc_url(home_url('/')); ?>" method="get">
<table>
<tr class="parent-tr">
<th>
<div class="th-inner">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/search.svg" alt="検索">検索項目
</div>
</th>
<td>
<label>
<input name="parent" type="radio" value="目的別" checked>
目的別
</label>
<label>
<input name="parent" type="radio" value="カテゴリー別">
カテゴリー別
</label>
</td>
</tr>
<tr class="keyword-tr">
<th>
<div class="th-inner">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/genre.svg" alt="ジャンル">ジャンルを探す
</div>
</th>
<td>
<div class="select-wrapper">
<select name="purpose" id="search-select" class="postform">
<option value="指定しない">指定しない</option>
<?php
$terms = get_terms('purpose',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo "<option class='level-0' value='$term->slug'>$term->name</option>";
}
?>
</select>
<div class="select-btn">
<img src="<?php echo get_template_directory_uri() ?>/assets/img/bottom-arrow.svg" alt="arrow">
</div>
</div>
</td>
</tr>
</table>
<input type="hidden" name="post_type" value="article">
<input type="hidden" name="s">
<button class="submit-btn" type="submit">
この条件で探す
</button>
</form>
- ラジオボタンを使用して、「目的別」と「カテゴリー別」の2つの検索オプションを提供している。name属性を「parent」に設定。また、checked属性で、「目的別」がデフォルトで選択されているようにする。
- セレクトボックス内部のoptionについて、カスタムタクソノミー「purpose」のタームを一覧表示させている。(デフォルトだけforeach文の外で「指定しない」のoptionタグを作っている)
解説② Javascript(jQuery)でセレクトボックスの中身を変わる機能を実装
<script>
let purpose = {
<?php
$terms = get_terms('purpose',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo $term->slug.":'".$term->name."',";
}
?>
}
let category = {
<?php
$terms = get_terms('article-cat',['hide_empty' => false]);
foreach ( $terms as $term ) {
echo $term->slug.":'".$term->name."',";
}
?>
}
jQuery('input[name="parent"]:radio').change(function(){
let parent = jQuery(this).val();
if(parent == '目的別') {
searchOption(purpose);
jQuery('#search-select').attr('name','purpose');
} else {
searchOption(category);
jQuery('#search-select').attr('name','article-cat');
}
})
function searchOption(n) {
jQuery('#search-select option').remove();
jQuery('#search-select').append('<option class="level-0" value>指定しない</option>');
jQuery.each(n, function(property,value){
jQuery('#search-select').append('<option class="level-0" value=' + property + '>' + value + '</option>');
})
}
</script>
- まず、JavaScript内で2つのオブジェクト(purposeとcategory)を定義している。これらのオブジェクトは、それぞれWordPressのカスタムタクソノミーである「purpose」と「article-cat」から取得したタームのスラッグと名前を保持している。PHPのforeach文を使ってタームを取得し、オブジェクトのプロパティとして出力している。
- 次に、ラジオボタンの値が変更されたときに実行されるイベントリスナーを設定している。ラジオボタンの値が「目的別」の場合、
searchOption
関数をpurposeオブジェクトを引数として呼び出し、さらに検索フォームのselect要素のname属性を「purpose」に設定する。それ以外の場合は、searchOption
関数をcategoryオブジェクトを引数として呼び出し、select要素のname属性を「article-cat」に設定する。 searchOption
関数では、まず引数として渡されたオブジェクトのプロパティを検索フォームのselect要素に追加する前に、既存のoption要素を削除する。次に、「指定しない」というデフォルトのoption要素を追加する。最後に、引数として渡されたオブジェクトのプロパティを反復処理し、それぞれのプロパティと値を使用して新しいoption要素を追加する。
PHP,Javascriptの基本を理解していれば、実装できる内容
なので、PHP,Javascript学びたて、というフェーズの方は、本機能実装にトライしてみると、いい復習の機会になる気もします。