0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Wordpress Gutenbergエディタで記事タイトルをバリデーションする方法

Last updated at Posted at 2025-06-18

標準の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;
  }
});
0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?