トップへ戻る
BLOGS

WordPress スライダーブロックの制作 (投稿スライドedit:編)

WordPress スライダーブロックの制作 (投稿スライドedit:編)

今回も前回の続きでWordPressのブロック制作です

今回は投稿記事を並べてスライダーを挿入するプラグインを作成していきます

前回までの記事で環境構築から管理画面の設定と編集画面のUI、
PHPでフロントエンドをレンダリングする画像ブロックを作成していたので
今回はその続きです

前回作成したブロックを利用して
投稿記事を選んでスライダーとして挿入できるようにするというところまでを目指します

※本記事はMacを使用したWordPressのローカル環境であり、Node.jsのインストール環境での開発を想定した記事です

さてそれでは続きを実装していきます

今回の目標

前回のレンダリング編として画像のスライダーは一旦完成しました
今回はツールバーの切り替えでこのスライダーを投稿のカテゴリーを選択してそのカテゴリーの記事をスライドで並べるという機能を実装したいと思います

その機能を実装するための概要です

  • ツールバーに切り替えボタンを実装
  • ツールバーでスライドを切り替える真偽値を属性値として設定
  • カテゴリーの値を保存するための属性値を設定
  • edit.jsで投稿を取得してくる(withSelect)
  • チェックが入ったカテゴリーをレンダリング
  • 画像スライダーとの棲み分けのためのリファクタリング

こんな感じですかね、、

ではまず上2つ、
ツールバーで切り替えを行えるようにします

ツールバーの実装

属性値の設定

ブロックを登録しているPHPファイルのattributesに以下を追記します

custom-slider.php

//投稿スライダーにする真偽値
'isPostSlider' => [
  'type'    => 'boolean',
  'default' => true
],
// selectedPostId を属性として追加
'selectedPostId' => [
  'type' => 'number',
  'default' => 0
],

続いてインスペクターを変更していきましょう

属性値を取得する関数を定義

まずは必要なコンポーネントから

edit.js

import {
  BlockControls,
} from "@wordpress/block-editor";
import {
  Toolbar,
} from "@wordpress/components";

それぞれ追加で Toolbar と BlockControls をインポートしておきます

edit.js

//ツールバーで投稿切り替えボタンを追加する関数
const getSliderChange = () => {
  return (
    <BlockControls>
      <Toolbar>
        <Button
          //属性 isPostSlider の値により表示するラベルを切り替え
          label={attributes.isPostSlider ? "画像スライド" : "投稿スライド"}
          //属性 isPostSlider の値により表示するアイコンを切り替え
          icon={attributes.isPostSlider ? "images-alt" : "wordpress"}
          className="imgChangeButton"
          //setAttributes を使って属性の値を更新(真偽値を反転)
          onClick={() =>
            setAttributes({ isPostSlider: !attributes.isPostSlider })
          }
        />
      </Toolbar>
    </BlockControls>
  );
};

<Button>コンポーネントで設定するのは属性値を使用して真偽値の切り替えです

setAttributes({ isPostSlider: !attributes.isPostSlider })

そしてその真偽値をもとに3項演算で label と iconを設定しておきます

次はこの関数を使用してreturnメソッドを変更していきます

returnメソッド変更

edit.js

return [
  getSliderChange(), //投稿スライド切り替えボタン
  getInspectorControls(), //インスペクター
  <div className={className}>
    {attributes.isPostSlider && (
      <Fragment>
        <MediaUploadCheck>
          <MediaUpload
            multiple={true}
            gallery={true}
            onSelect={onSelectImage}
            allowedTypes={["image"]}
            value={attributes.mediaID}
            render={({ open }) => getImageButton(open)}
          />
        </MediaUploadCheck>
        {attributes.imageUrl.length != 0 && ( // imageUrl(配列の長さ)で判定
          <MediaUploadCheck>
            <Button
              onClick={removeMedia}
              isLink
              isDestructive
              className="removeImage"
            >
              画像を削除
            </Button>
          </MediaUploadCheck>
        )}
      </Fragment>
    )}
    {!attributes.isPostSlider && (
      <div className={className}>
        <Placeholder
          label="投稿スライダー"
          icon="format-image"
          instructions="スライダーに表示する投稿を選択"
        >
          //
          ここに投稿用のメニューを作る
         //
        </Placeholder>
      </div>
    )}
  </div>,
];

まずはツールバーを表示できるようにgetSliderChange()を実行します

そして attributes.isPostSlider && で条件分岐を行い、 <Placeholder>コンポーネントで「投稿スライダー」であることを視認できるようにします

次はエディター画面で投稿を取得しリストにして選択できるようにします

投稿を取得してくる(withSelect)

この例では投稿のカテゴリーを選択する CategorySelect コンポーネントを別ファイル(posts-select.js)に定義し edit.js でインポートして使用するようにします

posts-select.js

const CategorySelect = (props) => {
  //ここに投稿のメニューを定義
};

WithSelect

以下では withSelect と定義した CategorySelect コンポーネントの組み合わせをデフォルトエクスポートすることで CategorySelect を拡張し、高階コンポーネントとしてreturnしています

posts-select.js

export default withSelect((select, props) => {
  //現在の投稿の post ID を取得
  const currentPostId = select("core/editor").getCurrentPostId();
  //クエリパラメータ
  const query = {
    per_page: -1,
    // exclude: currentPostId, //除外する投稿
  };
  return {
    posts: select("core").getEntityRecords("taxonomy", "oja_cat", query),
  };
})(CategorySelect);

順番に説明します

投稿の情報を取得するためにはwithSelect を使用します
まずは data モジュールから withSelect をインポートします

import { withSelect } from '@wordpress/data';

withSelect ではselect() を使用して、フェッチで取得したしたデータを props としてコンポーネントに渡すことがきる高階コンポーネントとなっています

高階コンポーネント

以下は高階コンポーネントの例で通常のEditメソッドを上書きする形になります

edit: withSelect( select => {
    return {
      //posts という select() の呼び出し結果をプロパティとするオブジェクトを返す
      posts: select('core').getEntityRecords('postType', 'post', { per_page: 3 })
    };
  })(Edit),

上記の例では Edit コンポーネントは posts という props を持ちます。withSelect 内で return するものは渡されたコンポーネント(この例では Edit)で props としてアクセスできるようになります

つまり下記のように投稿データを受け取れます

post-select.js

  const { posts } = props;
  

select()メソッド

select(‘core’) は 様々なデータにアクセスすることができ、以下の記述を記事編集画面のブラウザのコンソールに貼り付けて実行するとその主要メソッドを確認することができます

wp.data.select('core') 

投稿データを取得する際はgetEntityRecordsを使用します

今回はパラメータを以下に設定したためカスタムタクソノミーである投稿のいわゆるカテゴリーを取得しています

getEntityRecords( クエリーバー, スラッグ, パラメータ );

getEntityRecords("taxonomy", "oja_cat", query),

パラメータの設定として投稿を除外するには exclude: に投稿IDを渡します

exclude: = select("core/editor").getCurrentPostId();

getCurrentPostId() は現在の投稿のIDを返すため現在の投稿を除外することができます

次は受け取ったデータから <CategorySelect> コンポーネントを組み立ててみましょう

<CategorySelect> コンポーネント

post-select.js

import { MenuGroup, MenuItem } from "@wordpress/components";

const CategorySelect = (props) => {
  const { posts, selectedTermId, selectTerm } = props;

  return (
    <MenuGroup className="oja-posts-select">
      {posts &&
        posts.map((post) => (
          <MenuItem
            role="menuitemcheckbox"
            isSelected={post.id == selectedTermId}
            icon={post.id == selectedTermId ? "yes" : "marker"}
            onClick={() => selectTerm(post.id)}
          >
            {post.name}
          </MenuItem>
        ))}
    </MenuGroup>
  );
};

<MenuItem>

<MenuItem> はWordPressコンポーネントの一つで今回は単一選択を可能にしてくれます
role=”menuitemradio”とする事でラジオボタンとして機能します

新たに2つ変数を分割代入でインポートしてますがこれを edit.js で定義しておきます

edit.js

const selectTerm = (postId) => {
  setAttributes({ selectedPostId: postId });
};

シンプルに投稿のIDを受け取ってattributesの属性値にセットし直す関数です
それでは edit.js で <CategorySelect> を定義していきましょう

edit.js

import CategorySelect from "./posts-select";

// 中略
、、、、

{
  !attributes.isPostSlider && (
    <div className={className}>
      <Placeholder
        label="投稿スライダー"
        icon="format-image"
        instructions="スライダーに表示する投稿を選択"
      >
        <CategorySelect
          selectedTermId={attributes.selectedPostId}
          selectTerm={selectTerm}
        />
      </Placeholder>
    </div>
  );
}

selectedTermId={attributes.selectedPostId} とすることでvalueとして属性値を持つようにしてあります
この属性値は下記のメソッド
selectTerm={selectTerm}これにより書き換えられ、それによってアイコンやチェックマークの真偽値としています

投稿データの複数取得について

今回は単一のカテゴリーデータをもとにスライダーを生成しておりますが、

本来もう少し使い勝手を良くしたく、例えばすべての投稿一覧を表示してその中から選択した投稿をスライダーとして表示するなど、いい感じに仕上げたかったのですが、取得する配列データの受け渡しがうまく行かずやや妥協しました、、、

現在も勉強を続けておりReactのコンポーネントを自身の作るメソッドでマージしてうまく行かないかと考えております

一旦まとめ

長くなってきておりますがこれで管理画面上では投稿のデータを取得して並べられていると思います

今回は管理画面上の実装で区切り、次回からまたレンダリング編として表示とリファクタリングを行いたいと思います

お疲れさまでした

コメントをお待ちしております

お気軽にコメントをどうぞ。

CAPTCHA