23 β Edit/Save, attributes va InspectorControls¶
β¬ οΈ Oldingi: 22 β Custom blok yaratish asoslari Β· π README Β· Keyingi: 24 β Dinamik bloklar (render_callback) β‘οΈ
Bu bobda: 22-bobda blokni "qobiq" sifatida qurdik β endi unga jon kiritamiz. Blokning ikki yuragi bor:
edit(editorda nima ko'rinadi va qanday tahrirlanadi) vasave(frontga qanday HTML saqlanadi). Ular orasidagi ko'prik β attributes (blok ma'lumotlari). BizRichTextbilan matn tahrirlashni,attributesniblock.jsondatype/source/selectorbilan e'lon qilishni, ularnisetAttributesbilan yozishni, va o'ng sidebar'daInspectorControlsorqali sozlamalar panelini (TextControl, ToggleControl, ColorPalette, RangeControl) qurishni o'rganamiz. Hamma kod haqiqiynpx wp-scripts buildbilan (JSX transpilatsiyasi muvaffaqiyatli) tekshirilgan.
edit va save: blokning ikki yuragi¶
22-bobda biz blok block.json bilan ro'yxatdan o'tishini va index.js da registerBlockType chaqirilishini ko'rdik. Endi shu registerBlockType ga beriladigan ikki funksiyaga chuqur kiramiz:
registerBlockType( metadata.name, {
edit: Edit, // editorda ko'rinish (React komponent)
save, // frontga saqlanadigan HTML
} );
Ularni tushunish uchun bitta o'xshatish yetarli. Tasavvur qiling, blok β bu xat yozish:
editβ bu qog'oz va qalam: siz xatni yozasiz, o'chirib qayta yozasiz, joylashtirishni o'zgartirasiz. Interaktiv, jonli.saveβ bu konvert ichidagi tayyor xat: yozib bo'lgach, uni muhrlaysiz. O'quvchi (frontend) faqat shu tayyor natijani ko'radi, qalamingizni emas.
Texnik tilda:
edit |
save |
|
|---|---|---|
| Qachon ishlaydi | Faqat Gutenberg editorda | Saqlash paytida (bir marta) |
| Nimani qaytaradi | Tahrirlanadigan React UI | Statik HTML markup |
| Interaktivlik | Bor (onChange, sidebar) | Yo'q (faqat tayyor HTML) |
| Natija qayerda | Editor ekranida | post_content (bazada), keyin frontda |
setAttributes |
Bor | Yo'q (faqat o'qiydi) |
Eng muhim tushuncha shu: save ning natijasi bazaga matn (HTML) sifatida saqlanadi. Postni frontda ochganingizda WordPress JavaScript ishlatmaydi β u shunchaki saqlangan HTML'ni ko'rsatadi. Shuning uchun oddiy (statik) blok tez ishlaydi: front uchun React kerak emas. (Dinamik bloklar boshqacha β ular save o'rniga PHP render_callback ishlatadi, bu 24-bobning mavzusi.)
DIQQAT β eng ko'p uchraydigan boshlovchi xatosi:
savefunksiyasini o'zgartirib, blokni qayta yuklasangiz, WordPress "Bu blok kutilmagan yoki yaroqsiz kontentni o'z ichiga oladi" (block validation) ogohlantirishini beradi. Sababi: bazadagi eski HTML endi yangisavechiqaradigan HTML'ga mos kelmaydi. Buni keyinroq (oxirgi bo'limda)block.jsonversionva deprecation bilan qanday hal qilishni ko'ramiz.
Loyiha bloki: "Ogohlantirish qutisi"¶
Butun bob davomida bitta amaliy blok quramiz: ogohlantirish qutisi (notice/callout) β sarlavha, matn, ixtiyoriy ikonka va sozlanadigan fon rangi bilan. Bu blok hamma asosiy tushunchani (RichText, attributes, InspectorControls, supports) bitta joyda ko'rsatadi.
Fayl strukturasi (22-bobdagidek src/ papkada, wp-scripts build bilan quriladi):
ogohlantirish/
βββ package.json
βββ src/
βββ block.json <- metadata + attributes + supports
βββ index.js <- registerBlockType
βββ edit.js <- editor komponenti
βββ save.js <- frontga saqlash
βββ style.scss <- front + editor stil
βββ editor.scss <- faqat editor stil
RichText: tahrirlanadigan matn¶
Oddiy HTML'da matnni <p>matn</p> deb yozasiz. Lekin editorda foydalanuvchi matnni bevosita yozishi, qalin/kursiv qilishi kerak. Buning uchun @wordpress/block-editor dan keladigan RichText komponenti ishlatiladi.
import { RichText, useBlockProps } from '@wordpress/block-editor';
export default function Edit( { attributes, setAttributes } ) {
const { matn } = attributes;
const blockProps = useBlockProps();
return (
<p { ...blockProps }>
<RichText
tagName="p"
value={ matn }
onChange={ ( yangi ) => setAttributes( { matn: yangi } ) }
placeholder="Matn kiriting..."
/>
</p>
);
}
RichText ning to'rt asosiy propi:
| Prop | Vazifasi |
|---|---|
tagName |
Qaysi HTML teg yaratiladi (p, h2, span, div...) |
value |
Hozirgi matn β attributes dan keladi |
onChange |
Foydalanuvchi yozganda chaqiriladi β setAttributes bilan qiymatni saqlaymiz |
placeholder |
Bo'sh bo'lganda ko'rinadigan rangsiz ko'rsatma matn |
Bu yerda bir tomonlama ma'lumot oqimi (one-way data flow) deb ataladigan React tamoyili ishlaydi: value har doim attributes dan o'qiladi (haqiqat manbai β single source of truth), onChange esa o'sha manbani yangilaydi. Komponent o'zida holat (state) saqlamaydi β hamma narsa attributes da.
useBlockProps()nima? Bu hook blokning tashqi elementiga WordPress kutadigan barcha atributlarni (class,data-*, tekislash, rang class'lari) qo'shadi. Har bir blokning tashqi (root) elementiga uni qo'llash majburiy β aks holda blok editorda to'g'ri tanlanmaydi va supports (rang, spacing) ishlamaydi.
RichText'ni save da: RichText.Content¶
edit da RichText interaktiv komponentdir. save da esa bizga interaktivlik kerak emas β faqat tayyor HTML kerak. Shuning uchun RichText.Content ishlatiladi:
import { RichText, useBlockProps } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const { matn } = attributes;
const blockProps = useBlockProps.save();
return (
<p { ...blockProps }>
<RichText.Content tagName="p" value={ matn } />
</p>
);
}
Ikki farqni yodda tuting:
useBlockProps()o'rnigauseBlockProps.save()βsaveda har doim.save()variant.<RichText ... />o'rniga<RichText.Content ... />β onChange yo'q, faqatvalueni HTML'ga aylantiradi.
Agar matn = "Salom <strong>dunyo</strong>" bo'lsa, save quyidagini chiqaradi:
attributes: blokning xotirasi¶
Yuqorida attributes.matn ni ishlatdik β lekin u qayerdan keladi? Javob: block.json ning attributes bo'limidan. Attributes β blok saqlaydigan barcha ma'lumotlar: matn, ranglar, sonlar, true/false bayroqlar va h.k.
Har bir attribute to'rt mumkin bo'lgan maydonga ega:
| Maydon | Vazifasi | Misol |
|---|---|---|
type |
Ma'lumot turi | string, number, boolean, array, object |
source |
Qiymat qayerdan o'qiladi (saqlangan HTML ichidan) | html, text, attribute, query |
selector |
Qaysi HTML element bilan ishlaymiz | h4, p, img, a |
default |
Boshlang'ich qiymat (hech narsa kiritilmaganda) | "Diqqat", true, 8 |
{
"attributes": {
"sarlavha": {
"type": "string",
"source": "html",
"selector": "h4",
"default": "Diqqat"
},
"matn": {
"type": "string",
"source": "html",
"selector": "p"
},
"ikonkoYoq": {
"type": "boolean",
"default": true
},
"radius": {
"type": "number",
"default": 8
}
}
}
type β ma'lumot turi¶
Bu eng oddiy maydon. JSON turlaridan biri: string (matn), number (son), boolean (true/false), array (ro'yxat), object (ob'ekt). type deyarli har doim majburiy.
source va selector β qiymat qayerdan o'qiladi¶
Mana eng nozik tushuncha. WordPress attribute qiymatini ikki usuldan biri bilan saqlaydi:
1-usul: source YO'Q (attribute block kommentariga yoziladi)
Agar attribute'da source bo'lmasa (yuqorida ikonkoYoq va radius), WordPress qiymatni blok kommentari ichiga JSON sifatida yozadi:
<!-- wp:kitob/ogohlantirish {"ikonkoYoq":true,"radius":8} -->
<div class="...">...</div>
<!-- /wp:kitob/ogohlantirish -->
2-usul: source BOR (qiymat HTML ichidan o'qiladi)
Agar source: "html" va selector: "h4" bersangiz (sarlavha), WordPress qiymatni HTML markupning ichidan β h4 elementining ichidagi HTML'dan β o'qiydi. Kommentarda saqlanmaydi:
<!-- wp:kitob/ogohlantirish -->
<div class="..."><h4>Diqqat</h4><p>Matn...</p></div>
<!-- /wp:kitob/ogohlantirish -->
Bu yerda sarlavha qiymati <h4> ning ichidan, matn esa <p> ning ichidan qayta o'qiladi.
source ning asosiy qiymatlari:
source |
Nimani o'qiydi | Tipik ishlatilishi |
|---|---|---|
html |
Element ichidagi to'liq HTML | RichText (qalin/kursiv saqlash kerak) |
text |
Element ichidagi faqat oddiy matn | HTML formatlashsiz matn |
attribute |
HTML atribut qiymati (qo'shimcha attribute kalitidan) |
img ning src, a ning href |
query |
Bir nechta elementdan massiv | Ro'yxat (li elementlari) |
source: "attribute" misoli β rasm manzili:
Bu img elementining src atributidan qiymatni o'qiydi.
Qachon
sourceishlataman, qachon yo'q? Oddiy qoida: agar qiymatsavemarkupining ichida ko'rinsa (matn, sarlavha, rasm manzili) βsource/selectorbering, shunda u HTML'dan qayta o'qiladi va markup "haqiqat manbai" bo'ladi. Agar qiymat ko'rinmaydigan sozlama bo'lsa (true/false bayroq, raqamli radius, rang kodi) βsourcesiz qoldiring, u kommentarda JSON sifatida saqlanadi.
default β boshlang'ich qiymat¶
Blok birinchi qo'shilganda yoki qiymat hali kiritilmaganda ishlatiladigan qiymat. default: "Diqqat" bersangiz, yangi blokda sarlavha "Diqqat" bo'lib turadi.
setAttributes: qiymatni yozish¶
attributes ni o'qiy olasiz, lekin to'g'ridan-to'g'ri o'zgartira olmaysiz (attributes.matn = "..." ishlamaydi β React tamoyili). O'zgartirish uchun WordPress beradigan setAttributes funksiyasi ishlatiladi:
export default function Edit( { attributes, setAttributes } ) {
const { matn } = attributes;
// O'QISH: attributes dan
// YOZISH: setAttributes bilan
const yangileMatn = ( yangi ) => setAttributes( { matn: yangi } );
// ...
}
setAttributes ob'ekt qabul qiladi β faqat o'zgargan kalitlarni berasiz, qolganlari tegmaydi:
setAttributes( { matn: 'Yangi matn' } ); // faqat matn
setAttributes( { radius: 12, ikonkoYoq: false } ); // ikkita birdan
Bu β React'dagi setState ga o'xshaydi: u faqat ko'rsatilgan kalitlarni yangilaydi (qisman yangilash β merge), butun ob'ektni almashtirmaydi.
savedasetAttributesYO'Q.savefunksiyasiga faqat{ attributes }keladi,setAttributeskelmaydi. Sababi aniq:savesaqlash paytida bir marta ishlaydi, hech narsani o'zgartirmaydi β faqat hozirgi qiymatlardan HTML yasaydi.
InspectorControls: o'ng sidebar sozlamalari¶
RichText kanvasda bevosita tahrirlash uchun yaxshi. Lekin ba'zi sozlamalar matn emas β masalan ikonka ko'rsatish/ko'rsatmaslik, fon rangi, burchak radiusi. Bularni kanvasga qo'ymaymiz; ular editor o'ng tomonidagi sozlamalar panelida (Settings sidebar) bo'lishi kerak.
Buning uchun @wordpress/block-editor dan InspectorControls komponentini ishlatamiz. Uning ichiga qo'ygan hamma narsa avtomatik o'ng sidebar'ga ko'chadi:
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { PanelBody, ToggleControl } from '@wordpress/components';
export default function Edit( { attributes, setAttributes } ) {
const { ikonkoYoq } = attributes;
const blockProps = useBlockProps();
return (
<>
<InspectorControls>
<PanelBody title="Sozlamalar" initialOpen={ true }>
<ToggleControl
label="Ikonka korsatilsinmi"
checked={ ikonkoYoq }
onChange={ ( yangi ) => setAttributes( { ikonkoYoq: yangi } ) }
/>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
{ /* kanvas ko'rinishi shu yerda */ }
</div>
</>
);
}
E'tibor bering: return ichida ikki narsa bor β InspectorControls (sidebar) va div (kanvas). Ularni <>...</> (React Fragment) bilan o'rab beramiz, chunki funksiya bitta ildiz element qaytarishi kerak. InspectorControls ning o'zi kanvasda ko'rinmaydi β WordPress uni avtomatik sidebar'ga "ko'chiradi" (portal orqali).
PanelBody β yig'iluvchi panel bo'limi¶
@wordpress/components dan keladigan PanelBody β sozlamalarni guruhlaydigan, ochiluvchi/yopiluvchi bo'lim:
titleβ bo'lim sarlavhasi.initialOpenβ boshda ochiq (true) yoki yopiq (false) bo'lishi.
Bir nechta PanelBody ishlatib, sozlamalarni mantiqiy guruhlarga bo'lasiz (masalan "Tarkib", "Ko'rinish", "Kengaytirilgan").
@wordpress/components boshqaruvlari¶
@wordpress/components paketi tayyor, WordPress dizayniga mos UI komponentlar to'plamidir. Eng ko'p ishlatiladiganlari:
import {
PanelBody,
TextControl,
ToggleControl,
RangeControl,
ColorPalette,
} from '@wordpress/components';
| Komponent | Nima uchun | Asosiy proplar |
|---|---|---|
TextControl |
Matn kiritish maydoni | label, value, onChange |
ToggleControl |
Yoqish/o'chirish (true/false) | label, checked, onChange |
RangeControl |
Slayder (son tanlash) | label, value, onChange, min, max |
ColorPalette |
Rang tanlash palitra'si | value, onChange |
SelectControl |
Ochiluvchi ro'yxat | label, value, options, onChange |
Diqqat qiling: ToggleControl checked propini ishlatadi (boshqalar value). Bu tez-tez yangilanadigan xato β value bersangiz toggle ishlamaydi.
Har birining onChange i setAttributes bilan bog'lanadi:
<TextControl
label="Sarlavha"
value={ sarlavha }
onChange={ ( yangi ) => setAttributes( { sarlavha: yangi } ) }
/>
<RangeControl
label="Burchak radiusi (px)"
value={ radius }
onChange={ ( yangi ) => setAttributes( { radius: yangi } ) }
min={ 0 }
max={ 32 }
/>
<ColorPalette
value={ fonRangi }
onChange={ ( yangi ) => setAttributes( { fonRangi: yangi } ) }
/>
Import nomlarini ixtiro qilmang. Komponentlar aniq paketdan keladi: layout/RichText/InspectorControls/useBlockProps β
@wordpress/block-editor; UI boshqaruvlar (TextControl, ToggleControl...) β@wordpress/components;__()tarjima β@wordpress/i18n;registerBlockTypeβ@wordpress/blocks.wp-scriptsbu importlarni avtomatik WordPress global'lariga (wp.blockEditor,wp.components...) aylantiradi β npm'dan bu paketlar yuklab olinmaydi, ular WordPress'da allaqachon bor.
block supports: bepul UI¶
Ko'p sozlamalarni qo'lda yozish (rang uchun ColorPalette, padding uchun maydon...) zerikarli. WordPress qulay yo'l beradi: block.json ning supports bo'limi. Bitta true yozsangiz, WordPress mos sidebar boshqaruvini avtomatik qo'shadi β siz hech qanday JSX yozmaysiz.
{
"supports": {
"html": false,
"color": {
"background": true,
"text": true
},
"spacing": {
"padding": true,
"margin": true
},
"typography": {
"fontSize": true,
"lineHeight": true
}
}
}
Bu nima beradi:
supports kaliti |
Avtomatik qo'shiladigan UI |
|---|---|
color.background |
Sidebar'da fon rangi tanlovi |
color.text |
Matn rangi tanlovi |
spacing.padding |
Ichki bo'shliq (padding) boshqaruvi |
spacing.margin |
Tashqi bo'shliq (margin) boshqaruvi |
typography.fontSize |
Shrift o'lchami tanlovi |
typography.lineHeight |
Qator balandligi |
align |
Tekislash (["wide", "full"]) |
html: false |
"HTML sifatida tahrirlash" tugmasini o'chiradi (custom blokda tavsiya etiladi) |
supports ning sehri: WordPress nafaqat UI'ni qo'shadi, balki tanlangan qiymatni avtomatik saqlaydi va CSS class/style'ga aylantiradi β siz attributes ham, qo'shimcha JSX ham yozmaysiz. Masalan foydalanuvchi fon rangini tanlasa, WordPress has-{slug}-background-color class'ini yoki inline style'ni o'zi qo'shadi.
Qachon
supports, qachon o'z attribute'im? Standart dizayn sozlamalari (rang, bo'shliq, shrift) uchun β har doimsupports. Bu kamroq kod, WordPress standartlariga mos, theme.json bilan integratsiya qiladi. Faqatsupportsqoplamaydigan maxsus sozlama uchun (masalan bizning "ikonka ko'rsatilsinmi" bayrog'i) o'z attribute + InspectorControls yozasiz. Bizning blokda ikkalasini ham aralash ishlatamiz: rang/spacing/typography βsupports; ikonka/radius/sarlavha β o'z attributes.
To'liq, qurilgan blok¶
Mana yuqoridagi hamma tushunchani birlashtirgan to'liq blok. Bu kod vaqtinchalik papkada npx wp-scripts build bilan haqiqatan qurildi β JSX muvaffaqiyatli transpilatsiya qilindi, build/ papka hosil bo'ldi, block.json yaroqli JSON va barcha @wordpress/* importlari to'g'ri WordPress script handle'lariga (wp-block-editor, wp-blocks, wp-components, wp-i18n) bog'landi.
src/block.json¶
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "kitob/ogohlantirish",
"title": "Ogohlantirish qutisi",
"category": "text",
"icon": "warning",
"description": "Sarlavha va matnli ogohlantirish qutisi.",
"keywords": ["ogohlantirish", "notice", "callout"],
"textdomain": "kitob",
"attributes": {
"sarlavha": {
"type": "string",
"source": "html",
"selector": "h4",
"default": "Diqqat"
},
"matn": {
"type": "string",
"source": "html",
"selector": "p"
},
"ikonkoYoq": { "type": "boolean", "default": true },
"fonRangi": { "type": "string", "default": "#fef3c7" },
"radius": { "type": "number", "default": 8 }
},
"supports": {
"html": false,
"color": { "background": true, "text": true },
"spacing": { "padding": true, "margin": true },
"typography": { "fontSize": true, "lineHeight": true }
},
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css"
}
src/edit.js¶
import { __ } from '@wordpress/i18n';
import {
useBlockProps,
RichText,
InspectorControls,
} from '@wordpress/block-editor';
import {
PanelBody,
TextControl,
ToggleControl,
RangeControl,
ColorPalette,
} from '@wordpress/components';
export default function Edit( { attributes, setAttributes } ) {
const { sarlavha, matn, ikonkoYoq, fonRangi, radius } = attributes;
const blockProps = useBlockProps( {
className: 'kitob-ogohlantirish',
style: {
backgroundColor: fonRangi,
borderRadius: radius + 'px',
},
} );
return (
<>
<InspectorControls>
<PanelBody title={ __( 'Ogohlantirish sozlamalari', 'kitob' ) } initialOpen={ true }>
<ToggleControl
label={ __( 'Ikonka korsatilsinmi', 'kitob' ) }
checked={ ikonkoYoq }
onChange={ ( yangi ) => setAttributes( { ikonkoYoq: yangi } ) }
/>
<RangeControl
label={ __( 'Burchak radiusi (px)', 'kitob' ) }
value={ radius }
onChange={ ( yangi ) => setAttributes( { radius: yangi } ) }
min={ 0 }
max={ 32 }
/>
<TextControl
label={ __( 'Sarlavha (matnli)', 'kitob' ) }
value={ sarlavha }
onChange={ ( yangi ) => setAttributes( { sarlavha: yangi } ) }
/>
</PanelBody>
<PanelBody title={ __( 'Fon rangi', 'kitob' ) } initialOpen={ false }>
<ColorPalette
value={ fonRangi }
onChange={ ( yangi ) => setAttributes( { fonRangi: yangi } ) }
/>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
{ ikonkoYoq && <span className="kitob-ogohlantirish__ikonka">!</span> }
<RichText
tagName="h4"
value={ sarlavha }
onChange={ ( yangi ) => setAttributes( { sarlavha: yangi } ) }
placeholder={ __( 'Sarlavha kiriting...', 'kitob' ) }
/>
<RichText
tagName="p"
value={ matn }
onChange={ ( yangi ) => setAttributes( { matn: yangi } ) }
placeholder={ __( 'Matn kiriting...', 'kitob' ) }
/>
</div>
</>
);
}
src/save.js¶
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const { sarlavha, matn, ikonkoYoq, fonRangi, radius } = attributes;
const blockProps = useBlockProps.save( {
className: 'kitob-ogohlantirish',
style: {
backgroundColor: fonRangi,
borderRadius: radius + 'px',
},
} );
return (
<div { ...blockProps }>
{ ikonkoYoq && <span className="kitob-ogohlantirish__ikonka">!</span> }
<RichText.Content tagName="h4" value={ sarlavha } />
<RichText.Content tagName="p" value={ matn } />
</div>
);
}
src/index.js¶
import { registerBlockType } from '@wordpress/blocks';
import metadata from './block.json';
import Edit from './edit';
import save from './save';
import './style.scss';
import './editor.scss';
registerBlockType( metadata.name, {
edit: Edit,
save,
} );
E'tibor bering: edit va save bir xil kanvas markupini chiqaradi (div > ikonka + h4 + p). Bu edit/save mosligi qoidasi β save chiqaradigan HTML editor ko'rsatadigan strukturaga mos bo'lishi kerak, aks holda block validation xatosi chiqadi.
edit/save mosligi va block validation¶
Eng ko'p og'riq beradigan mavzu β qachon "Bu blok yaroqsiz kontentni o'z ichiga oladi" xatosi chiqadi va nima qilish kerak.
Nima sodir bo'ladi: WordPress postni ochganda, bazadagi saqlangan HTML'ni hozirgi save funksiyasi chiqaradigan HTML bilan solishtiradi. Agar ular bir xil bo'lmasa β validation xatosi.
Eng tipik sabab: siz save funksiyasini o'zgartirdingiz (masalan <div> ni <section> qildingiz yoki bitta class qo'shdingiz), lekin bazada eski markupli postlar bor. Endi ular mos kelmaydi.
Yechimlar:
- Yangi blok (hali post yo'q): muammo yo'q β shunchaki yangi
saveishlatiladi. - Mavjud postlar bor β
deprecatedishlatish: eskisavevariantinideprecatedmassiviga qo'shasiz, shunda WordPress eski markupni ham taniydi va avtomatik yangisiga o'tkazadi:
registerBlockType( metadata.name, {
edit: Edit,
save,
deprecated: [
{
attributes: metadata.attributes,
save: function eskiSave( { attributes } ) {
// eski markup (avvalgi versiya)
return <div>{ /* ... */ }</div>;
},
},
],
} );
- Vaqtinchalik (dev paytida): postni qaytadan saqlash yoki "Recover" tugmasini bosish.
Maslahat: blok ommaga chiqib, real postlarda ishlatilgach,
saveni o'zgartirsangiz β doimdeprecatedqo'shing. Aks holda foydalanuvchilarning postlari "buziladi". Yangi loyihada esa erkin o'zgartiring.
Tez-tez uchraydigan xatolar¶
useBlockProps()ni unutish. Root elementga{ ...blockProps }qo'ymasangiz, blok editorda to'g'ri tanlanmaydi vasupports(rang, spacing) ishlamaydi.savedauseBlockProps()ishlatish (.save()o'rniga).saveda har doimuseBlockProps.save().RichTextnisaveda ishlatish (RichText.Contento'rniga).saveda onChange bo'lmaydi β faqatRichText.Content.attributesni to'g'ridan-to'g'ri o'zgartirish.attributes.matn = "..."ishlamaydi β har doimsetAttributes({ matn: ... }).ToggleControlgavalueberish. Ucheckedishlatadi,valueemas.- Import paketini adashtirish.
RichText/InspectorControlsβ@wordpress/block-editor;TextControl/PanelBodyβ@wordpress/components. Aralashtirsangiz, build xato beradi. - edit va save markupi mos kelmasligi. Ikkalasi bir xil struktura chiqarishi kerak (yoki
deprecatedqo'shing) β aks holda validation xatosi. source/selectorni noto'g'ri ishlatish.selectorsaqlangan HTML'dagi haqiqiy element bo'lishi kerak.selector: "h4"desangiz,savedah4chiqishi shart, aks holda qiymat qayta o'qilmaydi.
Mashqlar¶
Oson¶
- Yangi attribute qo'shing.
block.jsongastringturlitugmaMatniattribute qo'shing (default: "Batafsil"). JSON yaroqli bo'lsin. - RichText sarlavhasi.
editdatagName="h3"bilansarlavhaattribute'ini tahrirlaydiganRichTextyozing (value,onChange,placeholderbilan). - save'da RichText.Content. 2-mashqdagi sarlavhaning
savevariantini yozing βRichText.Contentbilanh3chiqsin. - ToggleControl qo'shing.
ikonkoYoq(boolean) attribute uchun InspectorControls ichidaToggleControlyozing (checkedvaonChangeto'g'ri).
O'rta¶
source/selectorbelgilang.matnattribute'inisource: "html",selector: "p"bilan e'lon qiling vasaveda mos<p>chiqaring. Negasourceqo'shganimizni bir jumlada izohlang.- RangeControl bilan son.
chegaraQalinligi(number,default: 2) attribute qo'shing va InspectorControls'daRangeControl(min: 0,max: 10) bilan boshqaring. - ColorPalette bilan rang.
fonRangiattribute uchun PanelBody ichidaColorPaletteqo'ying.editvasavedastyle.backgroundColorga shu qiymatni bering. - block supports yoqing.
block.jsongasupportsqo'shing:color.background,spacing.padding,typography.fontSize. Har biri qaysi UI'ni qo'shishini izohlang.
Qiyin¶
- To'liq edit funksiya.
sarlavha(RichText),matn(RichText) va InspectorControls'daToggleControl+RangeControlbo'lgan to'liqedityozing.useBlockPropsroot'da bo'lsin. - Mos
savefunksiya. 9-mashqningsavevariantini yozing β markupeditkanvasiga mos bo'lsin (useBlockProps.save,RichText.Content). Nega ular mos bo'lishi kerakligini izohlang. source: "attribute". Rasmli blok uchunrasmUrlattribute'inisource: "attribute",selector: "img",attribute: "src"bilan e'lon qiling. Bu nimani qiladi β tushuntiring.- deprecated bilan migratsiya.
saveni<div>dan<section>ga o'zgartirdingiz deb tasavvur qiling. Eski postlar buzilmasligi uchunregisterBlockTypegadeprecatedqanday qo'shilishini yozing. - supports + custom attribute aralash. Bitta blokda: rang/spacing β
supportsorqali (block.json), ikonka ko'rsatish β o'z attribute +ToggleControlorqali boshqarilsin. Qaysi sozlama qaysi yo'l bilan kelishini izohlang. - SelectControl bilan variant.
darajaattribute (string,default: "info") qo'shing va InspectorControls'daSelectControlbilan uchta variant (info,ogohlantirish,xato) tanlash imkonini bering.
Yechimlar¶
Yechim β 1
type: "string" β matn turi. source yo'q, demak qiymat blok kommentariga JSON sifatida saqlanadi. default: "Batafsil" β yangi blokda boshlang'ich qiymat.
Yechim β 2
import { RichText } from '@wordpress/block-editor';
// edit ichida:
<RichText
tagName="h3"
value={ sarlavha }
onChange={ ( yangi ) => setAttributes( { sarlavha: yangi } ) }
placeholder="Sarlavha kiriting..."
/>
value har doim attributes dan o'qiladi (haqiqat manbai), onChange esa setAttributes bilan uni yangilaydi β bu bir tomonlama ma'lumot oqimi.
Yechim β 3
import { RichText } from '@wordpress/block-editor';
// save ichida:
<RichText.Content tagName="h3" value={ sarlavha } />
save da interaktivlik yo'q β RichText o'rniga RichText.Content, onChange ham yo'q. Bu <h3> ichiga sarlavha ning HTML'ini joylaydi (qalin/kursiv formatlash saqlanadi).
Yechim β 4
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, ToggleControl } from '@wordpress/components';
<InspectorControls>
<PanelBody title="Sozlamalar" initialOpen={ true }>
<ToggleControl
label="Ikonka korsatilsinmi"
checked={ ikonkoYoq }
onChange={ ( yangi ) => setAttributes( { ikonkoYoq: yangi } ) }
/>
</PanelBody>
</InspectorControls>
ToggleControl boolean qiymatni boshqaradi β checked (NE value) propini ishlatadi. onChange to'g'ridan-to'g'ri true/false beradi.
Yechim β 5
Nega source: matn qiymati save markupining ichida (<p> da) ko'rinadi. source: "html" + selector: "p" bilan WordPress qiymatni shu <p> ning ichidan qayta o'qiydi β markup haqiqat manbai bo'ladi, kommentar shishmaydi.
Yechim β 6
import { RangeControl } from '@wordpress/components';
<RangeControl
label="Chegara qalinligi (px)"
value={ chegaraQalinligi }
onChange={ ( yangi ) => setAttributes( { chegaraQalinligi: yangi } ) }
min={ 0 }
max={ 10 }
/>
type: "number" β son. RangeControl slayder ko'rinishida son tanlatadi; min/max chegaralarni belgilaydi. onChange to'g'ridan-to'g'ri sonni beradi.
Yechim β 7
import { InspectorControls } from '@wordpress/block-editor';
import { PanelBody, ColorPalette } from '@wordpress/components';
// InspectorControls ichida:
<PanelBody title="Fon rangi">
<ColorPalette
value={ fonRangi }
onChange={ ( yangi ) => setAttributes( { fonRangi: yangi } ) }
/>
</PanelBody>
ColorPalette value/onChange ishlatadi. Qiymat edit va save da bir xil style.backgroundColor ga berilishi kerak β shunda editor va front bir xil ko'rinadi.
Yechim β 8
{
"supports": {
"color": { "background": true },
"spacing": { "padding": true },
"typography": { "fontSize": true }
}
}
Har biri avtomatik sidebar UI qo'shadi:
- color.background -> fon rangi tanlovi (qo'shimcha JSX yozmasdan).
- spacing.padding -> ichki bo'shliq (padding) boshqaruvi.
- typography.fontSize -> shrift o'lchami tanlovi.
WordPress tanlangan qiymatni avtomatik saqlaydi va CSS class/style'ga aylantiradi β o'z attribute kerak emas.
Yechim β 9
import {
useBlockProps,
RichText,
InspectorControls,
} from '@wordpress/block-editor';
import { PanelBody, ToggleControl, RangeControl } from '@wordpress/components';
export default function Edit( { attributes, setAttributes } ) {
const { sarlavha, matn, ikonkoYoq, radius } = attributes;
const blockProps = useBlockProps( {
style: { borderRadius: radius + 'px' },
} );
return (
<>
<InspectorControls>
<PanelBody title="Sozlamalar" initialOpen={ true }>
<ToggleControl
label="Ikonka korsatilsinmi"
checked={ ikonkoYoq }
onChange={ ( yangi ) => setAttributes( { ikonkoYoq: yangi } ) }
/>
<RangeControl
label="Burchak radiusi (px)"
value={ radius }
onChange={ ( yangi ) => setAttributes( { radius: yangi } ) }
min={ 0 }
max={ 32 }
/>
</PanelBody>
</InspectorControls>
<div { ...blockProps }>
{ ikonkoYoq && <span className="ikonka">!</span> }
<RichText
tagName="h4"
value={ sarlavha }
onChange={ ( yangi ) => setAttributes( { sarlavha: yangi } ) }
placeholder="Sarlavha..."
/>
<RichText
tagName="p"
value={ matn }
onChange={ ( yangi ) => setAttributes( { matn: yangi } ) }
placeholder="Matn..."
/>
</div>
</>
);
}
<>...</> (Fragment) bilan InspectorControls va kanvas div birga qaytariladi. useBlockProps root div ga qo'llangan. Har bir boshqaruv setAttributes bilan bog'langan.
Yechim β 10
import { useBlockProps, RichText } from '@wordpress/block-editor';
export default function save( { attributes } ) {
const { sarlavha, matn, ikonkoYoq, radius } = attributes;
const blockProps = useBlockProps.save( {
style: { borderRadius: radius + 'px' },
} );
return (
<div { ...blockProps }>
{ ikonkoYoq && <span className="ikonka">!</span> }
<RichText.Content tagName="h4" value={ sarlavha } />
<RichText.Content tagName="p" value={ matn } />
</div>
);
}
Nega mos bo'lishi kerak: WordPress postni ochganda, bazadagi saqlangan HTML'ni hozirgi save chiqaradigan HTML bilan solishtiradi. Agar struktura (div > ikonka + h4 + p) edit kanvasiga mos kelmasa, "yaroqsiz kontent" (block validation) xatosi chiqadi. Shuning uchun edit va save bir xil markup yaratadi.
Yechim β 11
Bu nima qiladi: source: "attribute" qiymatni element ichidagi matndan emas, balki HTML atributidan o'qiydi. selector: "img" β qaysi element (<img>), attribute: "src" β qaysi atribut. Ya'ni WordPress saqlangan markupdagi <img src="..."> dan src qiymatini qayta o'qiydi. Bu rasm/havola bloklarida (img src, a href) ishlatiladi.
Yechim β 12
import { registerBlockType } from '@wordpress/blocks';
import metadata from './block.json';
import Edit from './edit';
import save from './save'; // YANGI: <section> chiqaradi
registerBlockType( metadata.name, {
edit: Edit,
save,
deprecated: [
{
attributes: metadata.attributes,
save: function eskiSave( { attributes } ) {
// ESKI markup: <div> ishlatardi
const blockProps = useBlockProps.save();
return <div { ...blockProps }>{ /* eski tarkib */ }</div>;
},
},
],
} );
deprecated massivi eski save variantlarini saqlaydi. WordPress postni ochganda avval hozirgi save (<section>) bilan solishtiradi; mos kelmasa, deprecated dagi eski save (<div>) bilan urinadi. Mos kelsa β eski markupni avtomatik yangisiga o'tkazadi (migratsiya), foydalanuvchi postlari buzilmaydi.
Yechim β 13
block.json (rang/spacing β supports):
{
"attributes": {
"ikonkoYoq": { "type": "boolean", "default": true }
},
"supports": {
"color": { "background": true, "text": true },
"spacing": { "padding": true }
}
}
edit (ikonka β custom attribute + ToggleControl):
<InspectorControls>
<PanelBody title="Sozlamalar">
<ToggleControl
label="Ikonka korsatilsinmi"
checked={ ikonkoYoq }
onChange={ ( yangi ) => setAttributes( { ikonkoYoq: yangi } ) }
/>
</PanelBody>
</InspectorControls>
Tushuntirish:
- Rang va padding β supports orqali keladi. WordPress UI'ni, attribute'ni va CSS'ni avtomatik boshqaradi β qo'shimcha JSX yozmaymiz.
- Ikonka ko'rsatish β supports qoplamaydigan maxsus mantiq. Shuning uchun o'z ikonkoYoq attribute + ToggleControl yozamiz va edit/save da { ikonkoYoq && <span>...</span> } bilan shartli render qilamiz.
Qoida: standart dizayn sozlamalari β supports; maxsus, blokka xos mantiq β o'z attribute.
Yechim β 14
import { SelectControl } from '@wordpress/components';
<SelectControl
label="Daraja"
value={ daraja }
options={ [
{ label: 'Ma\'lumot', value: 'info' },
{ label: 'Ogohlantirish', value: 'ogohlantirish' },
{ label: 'Xato', value: 'xato' },
] }
onChange={ ( yangi ) => setAttributes( { daraja: yangi } ) }
/>
SelectControl ochiluvchi ro'yxat beradi. options β har biri label (ko'rinadigan) va value (saqlanadigan) bo'lgan massiv. value joriy tanlovni attributes dan o'qiydi, onChange esa setAttributes bilan yangilaydi. Tanlangan daraja ni edit/save da CSS class sifatida ishlatish mumkin (masalan is-${daraja}).
β¬ οΈ Oldingi: 22 β Custom blok yaratish asoslari Β· π README Β· Keyingi: 24 β Dinamik bloklar (render_callback) β‘οΈ