標準のJavascriptで実装できます。
React.jsの環境構築やBabel.jsなどの用意も不要です。
Wordpressデータパッケージ(@wordpress/data
)の基本
以下の記事を読むと、ほぼすべてわかります
送信ボタンをロックする方法
記事編集画面で開発者ツールを開き、コンソール画面で以下のスクリプトを入れれば動作確認できます
wp.data.dispatch('core/editor').lockPostSaving('my-lock');
送信ボタンのロックを解除する方法
wp.data.dispatch('core/editor').unlockPostSaving('my-lock');
エラーメッセージを表示する方法
wp.data.dispatch('core/notices').createNotice(
'error',
'Please enter a title',
{ id: 'title-lock', isDismissible: false }
);
エラーメッセージを非表示にする方法
wp.data.dispatch('core/notices').removeNotice('title-lock');
具体例
以下に具体例として、記事タイトルに西暦だけ入れられるようにするバリデーションを掲載します。
仕様
- 特定の投稿タイプの時だけバリデーションを実行する
- 記事タイトルが西暦2000年~2200年の時だけ、送信可能にする
- 文字数が0~3文字、5文字以上の時は、送信不可能にする
下準備
まずは、jsファイルを然るべき場所に配置し、 functions.php
なり何なりで、読み込むようにします。
/wp-content/themes/your-theme/functions.php
function my_enqueue_scripts() {
wp_enqueue_script(
'my-title-validation',
'/wp-content/themes/your-theme/js/title-validation.js',
array('wp-edit-post', 'wp-data', 'wp-plugins', 'wp-element', 'wp-components'),
'1.0.0',
true
);
}
add_action('admin_enqueue_scripts', 'my_enqueue_scripts');
以下のような形で実装します
/wp-content/themes/your-theme/js/title-validation.js
wp.domReady(() => {
let prevTitle = null;
// バリデーション実行対象の投稿タイプを指定
const allowedPostTypes = ["events", "sports"];
// 入力状態を監視する(ページ読込直後はnull または undefined がしばらく続く)
wp.data.subscribe(() => {
const postType = wp.data.select("core/editor").getCurrentPostType();
//console.log("postType:", postType);
const isAllowedPostType = allowedPostTypes.includes(postType);
// 指定した投稿タイプの場合のみバリデーションを実行
if (!isAllowedPostType) return;
const postTitle = wp.data
.select("core/editor")
.getEditedPostAttribute("title");
// タイトルに変化がない場合は処理中止(Maximum call stack size exceededエラーを回避するため)
if (postTitle === prevTitle) {
return;
}
// 前回のタイトルと異なる場合のみバリデーションを実行
if (postTitle !== prevTitle) {
prevTitle = postTitle;
}
// バリデーションを実行
const handleTitleValidation = () => {
//console.log("postTitle:", postTitle);
const errorMessage = validateTitle(postTitle);
//console.log("errorMessage:", errorMessage);
// 初期化
wp.data.dispatch("core/notices").removeNotice("title-lock");
wp.data.dispatch("core/editor").unlockPostSaving("title-lock");
// エラーメッセージがある場合
if (errorMessage) {
// エラーメッセージを表示
wp.data
.dispatch("core/notices")
.createNotice("error", validationMessage(errorMessage), {
id: "title-lock",
isDismissible: true,
});
// 送信ボタンをロックする
wp.data.dispatch("core/editor").lockPostSaving("title-lock");
}
};
handleTitleValidation();
});
/**
* タイトルのバリデーションを行う
* @param {string} title タイトル
* @returns {string|null} エラーメッセージ
*/
function validateTitle(title) {
// 空文字チェックを最初に行う
if (isEmpty(title)) {
return "記事タイトルを入力してください。";
}
// 数字のみかチェック
if (!isNumeric(title)) {
return "記事タイトルは数字のみで入力してください。";
}
// 文字数チェック
if (!isValidLength(title)) {
return "記事タイトルは西暦4桁で入力してください。";
}
// 西暦の範囲チェック
const minYear = 2000;
const maxYear = 2200;
if (!isValidEra(title, minYear, maxYear)) {
return `記事タイトルは西暦${minYear}年から${maxYear}年の間で入力してください。`;
}
return null;
}
/**
* タイトルが空かどうかをチェックする
* @param {string} title タイトル
* @returns {boolean} タイトルが空かどうか
*/
function isEmpty(title) {
return !title || title.trim() === "";
}
/**
* タイトルが数字のみかどうかをチェックする
* @param {string} title タイトル
* @returns {boolean} タイトルが数字のみかどうか
*/
function isNumeric(title) {
return /^\d+$/.test(title);
}
/**
* タイトルの長さが4桁かどうかをチェックする
* @param {string} title タイトル
* @returns {boolean} タイトルの長さが4桁かどうか
*/
function isValidLength(title) {
return title.length === 4;
}
/**
* タイトルが有効な西暦の範囲内かどうかをチェックする
* @param {string} title タイトル
* @param {number} minYear 最小西暦
* @param {number} maxYear 最大西暦
* @returns {boolean} タイトルが有効な西暦の範囲内かどうか
*/
function isValidEra(title, minYear, maxYear) {
const year = parseInt(title, 10);
return year >= minYear && year <= maxYear;
}
/**
* エラーメッセージを返す
* @param {string} message エラーメッセージ
* @returns {string} エラーメッセージ
*/
function validationMessage(message) {
return message;
}
});