「詳細画面のボタン → POSTでフォームページへ遷移 → 案件名をフォームに表示」 の形で、WordPress用の最小サンプルを作ります。
今回は次の流れです。
• 詳細画面で「この案件に応募する」ボタンを押す
• POSTでフォームページへ移動する
• フォームページで 案件名 を受け取る
• フォームの入力欄にも表示する
• 確認画面にも表示する
• 最後の送信時にも案件名を持たせられる形にする
⸻
- 詳細画面テンプレートのサンプル
たとえば single-job.php など、案件詳細ページに置く例です。
<?php get_header(); ?>
<main id="main">
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<h1><?php the_title(); ?></h1>
<div class="entry-content">
<?php the_content(); ?>
</div>
<?php
// フォームページのURL
// 固定ページ「contact」のスラッグを想定
$form_page_url = home_url('/contact/');
?>
<form method="post" action="<?php echo esc_url($form_page_url); ?>">
<input type="hidden" name="jobtitle" value="<?php echo esc_attr(get_the_title()); ?>">
<button type="submit">この案件に応募する</button>
</form>
<?php endwhile; endif; ?>
</main>
<?php get_footer(); ?>
⸻
- フォームページ側でPOSTを受け取る
固定ページテンプレートや page-contact.php などで、最初に案件名を受け取ります。
<?php
get_header();
$jobtitle = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['jobtitle'])) {
$jobtitle = sanitize_text_field(wp_unslash($_POST['jobtitle']));
}
?>
<main id="main">
この $jobtitle を、あなたのフォームHTMLに差し込みます。
⸻
- フォームに「案件名」欄を追加する
HTMLに 案件名 を追加します。
input_area と confirm_area の両方に入れます。
入力画面に追加
氏名(必須) の前あたりに追加してください。
<label>案件名</label>
<input type="text" id="jobtitle" value="<?php echo esc_attr($jobtitle); ?>" readonly>
<!-- 最終送信用にも案件名を持たせるため hidden も置いておく -->
<input type="hidden" id="jobtitle_hidden" name="jobtitle" value="<?php echo esc_attr($jobtitle); ?>">
⸻
確認画面に追加
案件名:
たとえば確認画面はこうなります。
<div class="confirm_area">
<h2>入力内容確認</h2>
<p>以下の内容でよろしいですか?</p>
<strong>案件名:</strong><span class="confirm_jobtitle"></span>
<strong>お問合せ種別:</strong><span class="confirm_category"></span>
<strong>氏名:</strong><span class="confirm_uname"></span>
<strong>メールアドレス:</strong><span class="confirm_email"></span>
<strong>お住まい:</strong><span class="confirm_address"></span>
<strong>生年月日:</strong><span class="confirm_date"></span>
<strong>性別:</strong><span class="confirm_gender"></span>
<strong>メッセージ本文:</strong><span class="confirm_content"></span>
<button type="submit" class="submit_button">送信</button>
<button type="button" class="back_button">戻る</button>
</div>
⸻
- JSに案件名を確認画面へ反映する処理を追加
JSは change が起きた項目を確認画面へ入れる作りです。
ただし案件名は readonly で、ページ表示時点で値が入っているので、初期表示時に確認欄へセットしておくのが確実です。
DOMContentLoaded の中にこれを追加してください。
const jobtitleInput = document.querySelector("#jobtitle");
if (jobtitleInput) {
const confirmJobtitle = document.querySelector(".confirm_jobtitle");
if (confirmJobtitle) {
confirmJobtitle.textContent = jobtitleInput.value;
}
}
⸻
- フォーム全体に組み込んだ例
下は、WPでPOST受け取り済み の形にしたサンプルです。
あなたの元コードを大きく崩さず、必要部分だけ追加しています。
<?php
/*
Template Name: Contact Page
*/
get_header();
$jobtitle = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['jobtitle'])) {
$jobtitle = sanitize_text_field(wp_unslash($_POST['jobtitle']));
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>お問い合わせ</title>
<style>
.confirm_area,
.thanks_area {
display: none;
}
.wpcf7-response-output {
display: none;
}
.error-message {
color: #ff0000;
font-size: 0.8em;
margin-top: 5px;
display: none;
}
.input_area,
.confirm_area,
.thanks_area {
max-width: 600px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
label {
display: block;
margin: 15px 0 5px;
font-weight: bold;
}
input,
select,
textarea {
width: 100%;
padding: 8px;
margin: 5px 0;
border: 1px solid #ccc;
border-radius: 3px;
box-sizing: border-box;
}
input[type="radio"],
input[type="checkbox"] {
width: auto;
margin: 0 5px 0 0;
}
button {
background: #007cba;
color: white;
padding: 10px 20px;
border: none;
border-radius: 3px;
cursor: pointer;
margin: 10px 5px 0 0;
}
button:disabled {
background: #ccc;
cursor: not-allowed;
}
button:hover:not(:disabled) {
background: #005a87;
}
.confirm_area span {
font-weight: normal;
display: block;
margin: 5px 0 15px 0;
padding: 5px;
background: #f9f9f9;
border-left: 3px solid #007cba;
}
.thanks_area {
transition: opacity .5s ease;
}
</style>
</head>
<body>
<main id="main">
<!-- 入力画面 -->
<div class="input_area">
<h2>お問い合わせフォーム</h2>
<label>案件名</label>
<input type="text" id="jobtitle" value="<?php echo esc_attr($jobtitle); ?>" readonly>
<input type="hidden" id="jobtitle_hidden" name="jobtitle" value="<?php echo esc_attr($jobtitle); ?>">
<label>お問合せ種別</label>
<div id="category">
<label><input type="checkbox" name="category" value="お仕事のご相談" checked> お仕事のご相談</label>
<label><input type="checkbox" name="category" value="求人について"> 求人について</label>
<label><input type="checkbox" name="category" value="その他"> その他</label>
</div>
<label>氏名(必須)</label>
<input type="text" id="uname" aria-required="true">
<label>メールアドレス(必須)</label>
<input type="email" id="email" aria-required="true">
<p class="error-message" id="email-error"></p>
<label>メールアドレス(確認用)(必須)</label>
<input type="email" id="email_confirm" aria-required="true">
<p class="error-message" id="email-match-error">メールアドレスが一致していません</p>
<label>お住まい(必須)</label>
<select id="address" aria-required="true">
<option value="">選択してください</option>
<option value="北海道">北海道</option>
<option value="青森県">青森県</option>
<option value="秋田県">秋田県</option>
<option value="岩手県">岩手県</option>
<option value="宮城県">宮城県</option>
<option value="新潟県">新潟県</option>
</select>
<label>生年月日</label>
<input type="date" id="date" min="1980-01-01">
<label>性別</label>
<div id="gender">
<label><input type="radio" name="gender" value="女性" checked> 女性</label>
<label><input type="radio" name="gender" value="男性"> 男性</label>
</div>
<label>メッセージ本文</label>
<textarea id="content" rows="5"></textarea>
<button type="button" class="confirm_button" disabled>確認する</button>
</div>
<!-- 確認画面 -->
<div class="confirm_area">
<h2>入力内容確認</h2>
<p>以下の内容でよろしいですか?</p>
<strong>案件名:</strong><span class="confirm_jobtitle"></span>
<strong>お問合せ種別:</strong><span class="confirm_category"></span>
<strong>氏名:</strong><span class="confirm_uname"></span>
<strong>メールアドレス:</strong><span class="confirm_email"></span>
<strong>お住まい:</strong><span class="confirm_address"></span>
<strong>生年月日:</strong><span class="confirm_date"></span>
<strong>性別:</strong><span class="confirm_gender"></span>
<strong>メッセージ本文:</strong><span class="confirm_content"></span>
<button type="submit" class="submit_button">送信</button>
<button type="button" class="back_button">戻る</button>
</div>
<!-- 完了画面 -->
<div class="thanks_area">
<h2>送信完了</h2>
<p>お問合せいただきありがとうございました。<br>
2営業日以内に担当者よりご返信差し上げます。</p>
</div>
</main>
<script>
document.addEventListener("DOMContentLoaded", function () {
let val;
let id;
let radio;
let check;
let type;
let emailMatch = false;
const change_events = ["keydown", "keyup", "keypress", "change"];
// 案件名を初期反映
const jobtitleInput = document.querySelector("#jobtitle");
if (jobtitleInput) {
const confirmJobtitle = document.querySelector(".confirm_jobtitle");
if (confirmJobtitle) {
confirmJobtitle.textContent = jobtitleInput.value;
}
}
const items_radio = document.querySelectorAll("[type='radio']:checked");
items_radio.forEach(function (element) {
radio = element.value;
id = element.closest("[id]").id;
document.querySelector('.confirm_' + id).textContent = radio;
});
const items_checkbox = document.querySelectorAll("[type='checkbox']:checked");
items_checkbox.forEach(function (element) {
check = element.value;
id = element.closest("[id]").id;
document.querySelector('.confirm_' + id).textContent = check;
});
function validateEmails() {
const email = document.querySelector("#email").value;
const emailConfirm = document.querySelector("#email_confirm").value;
if (email !== "" && emailConfirm !== "") {
if (email !== emailConfirm) {
document.querySelector("#email-match-error").style.display = "block";
emailMatch = false;
} else {
document.querySelector("#email-match-error").style.display = "none";
emailMatch = true;
}
} else {
document.querySelector("#email-match-error").style.display = "none";
emailMatch = false;
}
checkRequiredFields();
}
const mail_match_fileds = ["#email", "#email_confirm"];
mail_match_fileds.forEach(function (selector) {
const mail_element = document.querySelector(selector);
change_events.forEach(function (event) {
mail_element.addEventListener(event, validateEmails);
});
});
const input_elements = document.querySelectorAll(".input_area input, .input_area select, .input_area textarea");
input_elements.forEach(function (element) {
element.addEventListener('change', function () {
val = this.value;
type = this.getAttribute("type");
if (type == "radio") {
radio = this.value;
id = this.closest("[id]").id;
document.querySelector(".confirm_" + id).textContent = radio;
}
else if (type == "checkbox") {
check = this.value;
id = this.closest("[id]").id;
let check_item = document.querySelector(".confirm_" + id);
if (this.checked) {
check_item.textContent += check + " / ";
} else {
check_item.textContent = check_item.textContent.replace(check + " / ", "");
}
}
else {
id = this.getAttribute("id");
if (id !== "email_confirm" && id !== "jobtitle_hidden") {
const other_val = this.value;
let other_item = document.querySelector(".confirm_" + id);
if (other_item) {
other_item.textContent = (other_val) ? other_val : "";
}
}
}
});
});
document.querySelector(".confirm_button").addEventListener("click", function () {
document.querySelector(".input_area").style.display = "none";
document.querySelector(".confirm_area").style.display = "block";
window.scrollTo({
top: 0,
behavior: "smooth"
});
});
document.querySelector(".back_button").addEventListener("click", function () {
document.querySelector(".input_area").style.display = "block";
document.querySelector(".confirm_area").style.display = "none";
window.scrollTo({
top: 0,
behavior: "smooth"
});
});
document.querySelector(".submit_button").addEventListener("click", function () {
const thanksArea = document.querySelector(".thanks_area");
document.querySelector(".confirm_area").style.display = "none";
window.scrollTo({
top: 0,
behavior: "smooth"
});
fadeIn(thanksArea);
});
function fadeIn(el) {
el.style.display = "block";
el.style.opacity = "0";
setTimeout(() => el.style.opacity = "1", 20);
}
function checkRequiredFields() {
const target = document.querySelectorAll('[aria-required="true"]');
let flag = true;
const confirm_btn = document.querySelector('.confirm_button');
target.forEach(function (e) {
if (e.value === "") {
flag = false;
}
});
if (flag && emailMatch) {
confirm_btn.removeAttribute("disabled");
} else {
confirm_btn.setAttribute("disabled", "");
}
}
change_events.forEach(event => {
const target = document.querySelectorAll('[aria-required="true"]');
target.forEach(function (e) {
e.addEventListener(event, function () {
checkRequiredFields();
});
});
});
});
</script>
</body>
</html>
<?php get_footer(); ?>
⸻
- この形でできること
このサンプルでできるのは次の内容です。
• 詳細ページのタイトルを POST で送る
• フォームページで $_POST['jobtitle'] を受け取る
• 案件名を readonly の入力欄に表示する
• 確認画面にも表示する
⸻
- 大事なポイント
① POSTはページ遷移時にだけ渡る
POST で渡した値は、その遷移時だけ です。
フォームページを直接開いたり、再読み込みの仕方によっては消えることがあります。
なので本番では、必要なら次のどれかにします。
• hidden に入れて次の送信まで保持する
• session に保存する
• URLパラメータで渡す
• DBに一時保存する
今回はサンプルとして、まず POSTで受け取り → hiddenにも入れて保持 にしています。
⸻
② 今の「送信」ボタンは実送信していない
あなたの現在のJSでは、送信ボタンを押しても
• 確認画面を消す
• 完了画面を出す
だけです。
つまり メール送信やDB保存はまだしていません。
本当に送るなら、次のどちらかが必要です。
•
• Contact Form 7 などに値を渡して送る
• Ajaxで送信する
⸻
③ チェックボックスは今のままだと複数値の扱いが少し不安定
今のコードは
check_item.textContent += check + " / ";
で足しているので、操作次第で表示が崩れることがあります。
必要なら次に チェックボックスを配列でまとめて確認画面へ出す版 も作れます。
⸻
- 最小差分だけ知りたい場合
あなたの元コードに対して本当に必要なのはこの3点です。
詳細画面側
<form method="post" action="<?php echo esc_url(home_url('/contact/')); ?>">
<input type="hidden" name="jobtitle" value="<?php echo esc_attr(get_the_title()); ?>">
<button type="submit">応募する</button>
</form>
フォームページ上部
<?php
$jobtitle = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['jobtitle'])) {
$jobtitle = sanitize_text_field(wp_unslash($_POST['jobtitle']));
}
?>
フォームに追加
<label>案件名</label>
<input type="text" id="jobtitle" value="<?php echo esc_attr($jobtitle); ?>" readonly>
<strong>案件名:</strong><span class="confirm_jobtitle"></span>
const jobtitleInput = document.querySelector("#jobtitle");
if (jobtitleInput) {
document.querySelector(".confirm_jobtitle").textContent = jobtitleInput.value;
}
⸻
必要なら次に、
「このフォームを本当にメール送信できる形」 にして、案件名も一緒に送る完全版までつなげて書けます。