Skip to content

Background Image Upload (MediaUpload, apiFetch, useEffect)

Fitur yang Dibangun

Menambahkan kemampuan untuk mengupload background image pada banner block melalui sidebar editor.


Import yang Diperlukan

js
import {
  InspectorControls,
  MediaUpload,
  MediaUploadCheck
} from "@wordpress/block-editor";

import {
  Button,
  PanelBody,
  PanelRow
} from "@wordpress/components";

import apiFetch from "@wordpress/api-fetch";
import { useEffect } from "@wordpress/element";

Catatan: Import useEffect dari @wordpress/element (bukan langsung dari React). WordPress membungkus React sebagai abstraction layer.


Attributes untuk Image

js
attributes: {
  imageID: { type: "number" },
  imgURL: { type: "string" }
}
AttributeFungsi
imageIDID media dari WordPress media library
imgURLURL gambar (disimpan setelah API fetch)

MediaUpload di InspectorControls

js
function EditComponent(props) {
  return (
    <>
      <InspectorControls>
        <PanelBody title="Background Image" initialOpen={true}>
          <PanelRow>
            <MediaUploadCheck>
              <MediaUpload
                onSelect={(media) => props.setAttributes({ imageID: media.id })}
                value={props.attributes.imageID}
                render={({ open }) => (
                  <Button onClick={open}>Choose Image</Button>
                )}
              />
            </MediaUploadCheck>
          </PanelRow>
        </PanelBody>
      </InspectorControls>
      
      {/* ... konten block lainnya */}
    </>
  );
}

Props MediaUpload

PropFungsi
onSelectCallback saat gambar dipilih → simpan media.id
valueID media yang sedang aktif
renderFunction yang return UI button → destructure { open }

Mengapa MediaUploadCheck?

Wrapper MediaUploadCheck memastikan button hanya muncul jika user memiliki izin untuk upload media.


Fetch URL Gambar dengan apiFetch & useEffect

Masalah

WordPress media picker memberikan ID media, tapi kita butuh URL gambar dengan ukuran custom (misal: page_banner).

Ukuran gambar custom (seperti page_banner) tidak tersedia di data default yang dikembalikan media picker.

Solusi: REST API + useEffect

js
function EditComponent(props) {
  // Watch perubahan imageID
  useEffect(() => {
    if (props.attributes.imageID) {
      async function fetchImage() {
        const response = await apiFetch({
          path: `/wp/v2/media/${props.attributes.imageID}`,
          method: "GET"
        });
        props.setAttributes({
          imgURL: response.media_details.sizes.page_banner.source_url
        });
      }
      fetchImage();
    }
  }, [props.attributes.imageID]);

  // ...
}

Alur Kerja

1. User pilih gambar → onSelect → imageID disimpan
2. useEffect mendeteksi imageID berubah
3. apiFetch ke /wp/v2/media/{id}
4. Response berisi media_details.sizes.page_banner.source_url
5. imgURL disimpan ke attributes
6. Background image ditampilkan

Endpoint REST API

GET /wp/v2/media/{id}

Response path ke URL gambar:

response.media_details.sizes.page_banner.source_url

Jika ukuran custom tidak ada, gunakan ukuran default: response.source_url


Fallback Image dengan wp_localize_script

Masalah

Bagaimana jika user tidak memilih gambar sama sekali? Kita butuh fallback default.

Solusi di PHP

Gunakan parameter ketiga di JSXBlock:

php
new JSXBlock("banner", true, array(
    'fallbackImage' => get_theme_file_uri('/images/library-hero.jpg')
));

Akses di JavaScript

js
// Data tersedia di window.banner.fallbackImage
wp.blocks.registerBlockType("ourBlockTheme/banner", {
  attributes: {
    imgURL: {
      type: "string",
      default: window.banner.fallbackImage  // Fallback dari PHP
    }
  }
  // ...
});

Cara Kerja wp_localize_script

PHP (server)                    →  JavaScript (client)
─────────────────────────────────────────────────────
get_theme_file_uri(...)         →  window.banner.fallbackImage
$data['fallbackImage']          →  Tersedia di global scope JS

File PHP Render: banner.php

php
<?php
if (!isset($attributes['imgURL'])) {
    $attributes['imgURL'] = get_theme_file_uri('/images/library-hero.jpg');
}
?>

<div class="page-banner">
    <div class="page-banner__bg-image"
         style="background-image: url('<?php echo esc_url($attributes['imgURL']); ?>');
                background-position: center center;">
    </div>
    <div class="page-banner__content container">
        <?php echo $content; ?>
    </div>
</div>

CSS Fix: Tambahkan background-position: center center agar gambar selalu terpusat.


Kesimpulan

KomponenFungsi
MediaUploadUI untuk memilih gambar dari media library
MediaUploadCheckWrapper — cek permission upload
apiFetchFetch REST API WordPress (async)
useEffectWatch imageID → fetch URL gambar
/wp/v2/media/{id}Endpoint untuk detail media (termasuk custom sizes)
wp_localize_scriptKirim data dari PHP ke JS (fallback image)
isset() checkDi PHP render: gunakan fallback jika imgURL kosong