Skip to content

Migrasi Slide & Slideshow Blocks

Gambaran Umum

Slide dan slideshow block mengikuti pola yang sama dengan banner block. Slide = hampir identik dengan banner (background image + InnerBlocks). Slideshow = wrapper sederhana yang menampung beberapa slide.

Slide Block

Langkah 1: functions.php

php
// Hapus/comment out:
// new JSXBlock("slide", true, [...]);

// Tambahkan di ourNewBlocks():
register_block_type_from_metadata(__DIR__ . "/build/slide");

Langkah 2: Duplikasi folder banner

Duplikasi src/banner/ → rename jadi src/slide/ (karena sangat mirip).

Langkah 3: block.json

json
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "ourblocktheme/slide",
  "title": "Slide",
  "supports": {
    "align": ["full"]
  },
  "attributes": {
    "align": {
      "type": "string",
      "default": "full"
    },
    "themeimage": {
      "type": "string"
    },
    "imgID": {
      "type": "number"
    },
    "imgURL": {
      "type": "string"
    }
  },
  "editorScript": "file:./index.js",
  "render": "file:./render.php"
}

Perbedaan dari banner:

  • Tambah attribute themeimage (type: string) — untuk default image dari template HTML
  • Ini diperlukan agar WordPress mengenali attribute themeimage yang datang dari template file

Langkah 4: render.php

Copy dari our-blocks/slide.php:

php
<div class="hero-slider__slide" 
     style="background-image: url(<?php echo esc_url($attributes['imgURL']); ?>)">
  <div class="hero-slider__interior container">
    <div class="hero-slider__overlay">
      <?php echo $content; ?>
    </div>
  </div>
</div>

Langkah 5: edit.js

Hampir identik dengan banner, tapi punya logika themeimage untuk fallback:

js
import { InspectorControls, MediaUpload, MediaUploadCheck, InnerBlocks, useBlockProps } from "@wordpress/block-editor";
import { PanelBody, PanelRow } from "@wordpress/components";
import { useEffect } from "@wordpress/element";
import apiFetch from "@wordpress/api-fetch";

export default function Edit(props) {
  const blockProps = useBlockProps();

  // useEffect 1: Set imgURL dari themeimage (default dari template)
  useEffect(() => {
    if (props.attributes.themeimage) {
      props.setAttributes({
        imgURL: `${ourThemeData.themePath}/images/${props.attributes.themeimage}`
      });
    }
  }, [props.attributes.themeimage]);

  // useEffect 2: Fallback jika TIDAK ada themeimage DAN belum ada imgURL
  useEffect(() => {
    if (!props.attributes.themeimage && !props.attributes.imgURL) {
      props.setAttributes({
        imgURL: `${ourThemeData.themePath}/images/library-hero.jpg`
      });
    }
  }, []);

  // useEffect 3: Fetch image URL dari media ID (saat user upload gambar)
  useEffect(() => {
    if (props.attributes.imgID) {
      async function go() {
        const response = await apiFetch({
          path: `/wp/v2/media/${props.attributes.imgID}`,
          method: "GET",
        });
        props.setAttributes({
          imgURL: response.media_details.sizes.pageBanner?.source_url 
                  ?? response.media_details.sizes.full.source_url,
        });
      }
      go();
    }
  }, [props.attributes.imgID]);

  function onFileSelect(x) {
    props.setAttributes({ imgID: x.id });
  }

  return (
    <div {...blockProps}>
      <InspectorControls>
        <PanelBody title="Background" initialOpen={true}>
          <PanelRow>
            <MediaUploadCheck>
              <MediaUpload
                onSelect={onFileSelect}
                value={props.attributes.imgID}
                render={({ open }) => (
                  <button className="button button-large" onClick={open}>
                    Choose Background Image
                  </button>
                )}
              />
            </MediaUploadCheck>
          </PanelRow>
        </PanelBody>
      </InspectorControls>

      <div className="hero-slider__slide"
           style={{ backgroundImage: `url('${props.attributes.imgURL}')` }}>
        <div className="hero-slider__interior container">
          <div className="hero-slider__overlay">
            <InnerBlocks allowedBlocks={[
              "ourblocktheme/genericheading",
              "ourblocktheme/genericbutton"
            ]} />
          </div>
        </div>
      </div>
    </div>
  );
}

Logika themeimage Explained

Template file (front-page.html) bisa menyediakan default image per slide:

html
<!-- wp:ourblocktheme/slide {"themeimage":"bus.jpg"} -->
  <!-- inner blocks -->
<!-- /wp:ourblocktheme/slide -->
  • Slide 1: themeimage: "bus.jpg"ourThemeData.themePath + "/images/bus.jpg"
  • Slide 2: themeimage: "apples.jpg"ourThemeData.themePath + "/images/apples.jpg"
  • Slide baru (tanpa themeimage): → fallback ke library-hero.jpg

Langkah 6: index.js (sama dengan banner)

js
import { registerBlockType } from "@wordpress/blocks";
import { InnerBlocks } from "@wordpress/block-editor";
import metadata from "./block.json";
import Edit from "./edit";

registerBlockType(metadata.name, {
  edit: Edit,
  save: () => {
    return <InnerBlocks.Content />;
  },
});

Slideshow Block

Langkah 1: functions.php

php
// Hapus/comment out:
// new JSXBlock("slideshow", false);

// Tambahkan di ourNewBlocks():
register_block_type_from_metadata(__DIR__ . "/build/slideshow");

Langkah 2: Duplikasi folder slide → rename slideshow

Langkah 3: block.json (Lebih Sederhana)

json
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "ourblocktheme/slideshow",
  "title": "Slideshow",
  "supports": {
    "align": ["full"]
  },
  "attributes": {
    "align": {
      "type": "string",
      "default": "full"
    }
  },
  "editorScript": "file:./index.js",
  "render": "file:./render.php"
}

Slideshow TIDAK butuh themeimage, imgID, atau imgURL — itu urusan setiap slide individual.

Langkah 4: render.php

Copy dari our-blocks/slideshow.php (Glide.js wrapper):

php
<div class="hero-slider">
  <div data-glide-el="track" class="glide__track">
    <div class="glide__slides">
      <?php echo $content; ?>
    </div>
  </div>
  <div data-glide-el="controls">
    <button data-glide-dir="<">Prev</button>
    <button data-glide-dir=">">Next</button>
  </div>
</div>

Langkah 5: edit.js (Sangat Sederhana)

js
import { InnerBlocks, useBlockProps } from "@wordpress/block-editor";

export default function Edit() {
  const blockProps = useBlockProps();

  return (
    <div {...blockProps}>
      <div className="hero-slider">
        <InnerBlocks allowedBlocks={["ourblocktheme/slide"]} />
      </div>
    </div>
  );
}

Catatan:

  • Tidak perlu props parameter (tidak ada dynamic attributes)
  • Tidak perlu useEffect atau apiFetch
  • Hanya InnerBlocks yang mengizinkan block slide saja
  • Tetap butuh useBlockProps wrapper

Langkah 6: index.js (sama)

js
import { registerBlockType } from "@wordpress/blocks";
import { InnerBlocks } from "@wordpress/block-editor";
import metadata from "./block.json";
import Edit from "./edit";

registerBlockType(metadata.name, {
  edit: Edit,
  save: () => {
    return <InnerBlocks.Content />;
  },
});

Setelah Selesai: Hapus File Lama

Hapus dari our-blocks/:
  ✗ slide.js
  ✗ slide.php
  ✗ slideshow.js
  ✗ slideshow.php
  ✗ banner.js
  ✗ banner.php

Ringkasan Perbedaan Slide vs Slideshow vs Banner

FiturBannerSlideSlideshow
Background Image
themeimage attr
InnerBlocksheading + buttonheading + buttonslide
InspectorControls✅ (MediaUpload)✅ (MediaUpload)
useEffect2x (fallback + fetch)3x (theme + fallback + fetch)
Kompleksitas edit.jsTinggiTinggiRendah