Skip to content

Admin Options, Block Preview & block.json

Gambaran Umum

Video ini membahas cara menambahkan opsi admin di sidebar (InspectorControls) dan toolbar (BlockControls), menggunakan ColorPicker + third-party color picker, menambahkan block preview dan description, serta migrasi ke file block.json dengan apiVersion 2.


1. InspectorControls — Panel Sidebar Kanan

Import dari masing-masing package:

jsx
import { InspectorControls, BlockControls, AlignmentToolbar } from "@wordpress/block-editor"
import { PanelBody, PanelRow } from "@wordpress/components"

Struktur di JSX

jsx
function OurQuizEdit(props) {
  return (
    <div>
      {/* Panel sidebar kanan */}
      <InspectorControls>
        <PanelBody title="Background Color" initialOpen={true}>
          <PanelRow>
            {/* Color picker di sini */}
          </PanelRow>
        </PanelBody>
      </InspectorControls>

      {/* Inline toolbar atas block */}
      <BlockControls>
        <AlignmentToolbar
          value={props.attributes.theAlignment}
          onChange={(x) => props.setAttributes({ theAlignment: x })}
        />
      </BlockControls>

      {/* Konten block utama */}
      <div style={{
        backgroundColor: props.attributes.bgColor,
        textAlign: props.attributes.theAlignment
      }}>
        {/* ... form fields, answers, dll */}
      </div>
    </div>
  );
}

Penjelasan Components

ComponentLokasiFungsi
InspectorControlsSidebar kanan (Settings panel)Container untuk opsi block
PanelBodyDalam InspectorControlsCollapsible section
PanelRowDalam PanelBodySatu baris opsi
BlockControlsToolbar atas blockInline toolbar
AlignmentToolbarDalam BlockControlsLeft/center/right alignment

2. ColorPicker — WordPress Default

jsx
import { ColorPicker } from "@wordpress/components"
jsx
<PanelBody title="Background Color" initialOpen={true}>
  <PanelRow>
    <ColorPicker
      color={props.attributes.bgColor}
      onChangeComplete={(x) => props.setAttributes({ bgColor: x.hex })}
    />
  </PanelRow>
</PanelBody>

Perhatian: onChangeComplete bukan onChange

jsx
// ❌ SALAH — onChange memberikan real-time setiap pixel drag
onChange={(x) => props.setAttributes({ bgColor: x.hex })}

// ✅ BENAR — onChangeComplete hanya fire setelah user selesai memilih
onChangeComplete={(x) => props.setAttributes({ bgColor: x.hex })}

x.hex mengekstrak string hex color (contoh: "#ff0000").


3. Third-Party Color Picker (react-color)

Install

bash
npm install react-color

Import ChromePicker

jsx
import { ChromePicker } from "react-color"

Gunakan di JSX

jsx
<PanelBody title="Background Color" initialOpen={true}>
  <PanelRow>
    <ChromePicker
      color={props.attributes.bgColor}
      onChangeComplete={(x) => props.setAttributes({ bgColor: x.hex })}
      disableAlpha={true}
    />
  </PanelRow>
</PanelBody>

Perbedaan Default vs react-color

FiturWP ColorPickerChromePicker
InstallTidak perlunpm install react-color
Bundle size0 (built-in)Tambah ~beberapa KB
LookWP nativeChrome DevTools style
Alpha/opacityYaBisa di-disable

4. Attributes Baru

jsx
registerBlockType("ourplugin/are-you-paying-attention", {
  attributes: {
    question: { type: "string" },
    answers: { type: "array", default: [""] },
    correctAnswer: { type: "string", default: undefined },
    bgColor: { type: "string", default: "#EBEBEB" },       // ★ Baru
    theAlignment: { type: "string", default: "left" }       // ★ Baru
  },
  // ...
})

5. Frontend Style Props

Penting: Akses Props Berbeda di Frontend

jsx
// Admin (index.js) — lewat props.attributes
style={{ backgroundColor: props.attributes.bgColor }}

// Frontend (frontend.js) — langsung di props (tidak ada .attributes)
style={{ 
  backgroundColor: props.bgColor,
  textAlign: props.theAlignment 
}}

Karena di frontend kita spread data langsung: <Quiz {...data} />.


6. Block Preview & Description

Example Property — Preview di Block Inserter

jsx
registerBlockType("ourplugin/are-you-paying-attention", {
  // ...
  example: {
    attributes: {
      question: "What is my name?",
      answers: ["Meowsalot", "Barksalot", "Purrsloud", "Brad"],
      correctAnswer: "3",
      bgColor: "#CFE8F1",
      theAlignment: "center"
    }
  },
  // ...
})

Ketika user hover di list block inserter, preview muncul di panel kanan. Tanpa example, tidak ada preview.

Description Property

jsx
registerBlockType("ourplugin/are-you-paying-attention", {
  title: "Are You Paying Attention?",
  description: "Give your audience a chance to prove their comprehension.",
  // ...
})

Teks description muncul di sidebar kanan ketika block di-select.


7. Migrasi ke block.json

Sebelum (Manual Registration)

php
// PHP
function onInit() {
  wp_register_script('ournewblocktype', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-editor'));
  wp_register_style('ournewblocktype', plugin_dir_url(__FILE__) . 'build/index.css');
  register_block_type('ourplugin/are-you-paying-attention', array(
    'editor_script' => 'ournewblocktype',
    'editor_style' => 'ournewblocktype',
    'render_callback' => 'theHTML'
  ));
}
add_action('init', 'onInit');

Sesudah (block.json)

block.json:

json
{
  "apiVersion": 2,
  "name": "ourplugin/are-you-paying-attention",
  "title": "Are You Paying Attention?",
  "category": "common",
  "description": "Give your audience a chance to prove their comprehension.",
  "editorScript": "file:./build/index.js",
  "editorStyle": "file:./build/index.css"
}

PHP (lebih sederhana):

php
function onInit() {
  register_block_type(__DIR__, array(
    'render_callback' => 'theHTML'
  ));
}
add_action('init', 'onInit');

__DIR__ mengarah ke folder yang mengandung block.json. WordPress otomatis membaca file tersebut.


8. apiVersion 2 & useBlockProps

Import useBlockProps

jsx
import { useBlockProps, InspectorControls, BlockControls, AlignmentToolbar } from "@wordpress/block-editor"

Gunakan di Edit Function

jsx
function OurQuizEdit(props) {
  const blockProps = useBlockProps({
    className: "paying-attention-edit-block",
    style: { backgroundColor: props.attributes.bgColor }
  })

  return (
    <div {...blockProps}>
      <InspectorControls>
        {/* ... */}
      </InspectorControls>
      <BlockControls>
        {/* ... */}
      </BlockControls>
      {/* konten block ... */}
    </div>
  )
}

Apa yang useBlockProps Lakukan?

  • Menambahkan class dan ID yang diperlukan WordPress untuk mengidentifikasi block
  • Menambahkan atribut data-block
  • Menambahkan style dan className yang kamu berikan
  • Wajib untuk apiVersion 2 — block tidak berfungsi tanpa ini

Spread Operator

jsx
<div {...blockProps}>

Ini menyebarkan semua properti yang dikembalikan useBlockProps() ke elemen div.


9. Properties block.json untuk Asset Loading

json
{
  "editorScript": "file:./build/index.js",
  "editorStyle": "file:./build/index.css",
  "style": "file:./build/style-index.css",
  "script": "file:./build/frontend.js",
  "viewScript": "file:./build/frontend.js"
}
PropertyDimuat DiKeterangan
editorScriptEditor sajaJavaScript untuk admin/editor
editorStyleEditor sajaCSS untuk admin/editor
styleEditor + FrontendCSS yang berlaku di keduanya
scriptEditor + FrontendJS yang berlaku di keduanya
viewScriptFrontend sajaJS hanya untuk pengunjung

⚠️ Masalah viewScript + render_callback

viewScript TIDAK bekerja jika kamu menggunakan render_callback (dynamic block)

Ini adalah keterbatasan WordPress. viewScript otomatis dimuat hanya untuk static blocks yang menyimpan HTML di database.

Workaround: script + DOMContentLoaded

Jika kamu terpaksa menggunakan script (dimuat di editor+frontend):

jsx
// frontend.js
document.addEventListener("DOMContentLoaded", function() {
  // Kode hanya berjalan setelah DOM siap
  const divsToUpdate = document.querySelectorAll(".paying-attention-update-me")
  // ...
})

Wrapper DOMContentLoaded memastikan kode tidak berjalan sebelum HTML ada di halaman.


10. Rekomendasi Brad

Brad tidak menggunakan viewScript/script di block.json untuk frontend JS. Ia tetap memuat secara manual di PHP:

php
function theHTML($attributes) {
  if (!is_admin()) {
    wp_enqueue_script(
      'attentionFrontend',
      plugin_dir_url(__FILE__) . 'build/frontend.js',
      array('wp-element'),
      '1.0',
      true
    );
    wp_enqueue_style(
      'attentionFrontendStyles',
      plugin_dir_url(__FILE__) . 'build/frontend.css'
    );
  }
  
  ob_start(); ?>
  <div class="paying-attention-update-me">
    <pre style="display: none;"><?php echo wp_json_encode($attributes) ?></pre>
  </div>
  <?php return ob_get_clean();
}

Alasan

  1. Kontrol penuh kapan dan bagaimana JS dimuat
  2. Tidak kena bug viewScript + render_callback
  3. Conditional loading — hanya load jika block benar-benar ada di halaman
  4. block.json hanya untuk editorScript dan editorStyle

Ringkasan File Structure Final

are-you-paying-attention/
├── block.json                    ← Block registration metadata
├── are-you-paying-attention.php  ← PHP plugin file
├── node_modules/                 ← Dependencies
├── package.json                  ← Build scripts (build + start)
├── src/
│   ├── index.js                  ← Editor/admin React component
│   ├── index.scss                ← Editor styles
│   ├── frontend.js               ← Frontend React component
│   └── frontend.scss             ← Frontend styles
└── build/
    ├── index.js                  ← Compiled editor JS
    ├── index.css                 ← Compiled editor CSS
    ├── frontend.js               ← Compiled frontend JS
    └── frontend.css              ← Compiled frontend CSS