Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Using Blocks Outside The Editor
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Tom J Nowell
June 22, 2019
Technology
1.2k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Using Blocks Outside The Editor
Tom J Nowell
June 22, 2019
More Decks by Tom J Nowell
See All by Tom J Nowell
Composer_and_WordPress__1_.pdf
tarendai
0
98
REST APIs for Absolute Beginners
tarendai
0
1.1k
VVV 2
tarendai
0
930
WordCamp Europe 2016 - Handling Anxiety
tarendai
1
610
Escape From New York
tarendai
0
840
WP The Right Way
tarendai
0
1.2k
Code Deodorant 2014
tarendai
1
850
Adv WP CLI
tarendai
0
800
WP CLI
tarendai
0
770
Other Decks in Technology
See All in Technology
カンファレンスに参加した後の浮遊感とセルフケア
pauli
0
320
LocalStack を使ったサーバーレスアプリケーション開発 / Serverless Development with LocalStack
kakakakakku
1
350
自律型 AI をセキュアに実装!Gemini と MIG で作る動的コード実行環境
recruitengineers
PRO
1
240
AI 時代の Azure エンジニアリング ~ 私たちは何を磨き、何を任せるのか ~
chack411
1
560
二歩目のフロントエンド・ウェブアクセシビリティ
camiha
2
270
AI時代のAPI開発を加速する品質ガードレール / API Quality Guardrails in the AI Era
yokawasa
0
170
20260930_Gemma4_Hands-on
tsho
0
250
ハードウェアコンペでもAI駆動開発が進んでいる話
iotengineer22
1
660
OR学会2026年秋期大会_機械学習と数理最適化の融合による、配合レシピ最適化システム開発事例
brainpadpr
0
110
分析の民主化を支えるメタデータ整備の実践
kakehashi
PRO
4
1.2k
今こそ知りたいAmplifyGen2
mkdev10
2
160
OSC2026on_the-world-is-waiting-for-your-voice.pdf
naruoga
0
370
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.3k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
420
Fashionably flexible responsive web design (full day workshop)
malarkey
409
67k
We Are The Robots
honzajavorek
0
390
VelocityConf: Rendering Performance Case Studies
addyosmani
331
25k
Making the Leap to Tech Lead
cromwellryan
135
10k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
Music & Morning Musume
bryan
48
7.4k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.3k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.4k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
400
Optimizing for Happiness
mojombo
378
71k
Transcript
@tarendai https://tomjn.com Using Blocks Outside The Editor
@tarendai https://tomjn.com
@tarendai https://tomjn.com Frontenberg https://frontenberg.tomjn.com
@tarendai https://tomjn.com
@tarendai https://tomjn.com Frontenberg Is not a frontend editor!
@tarendai https://tomjn.com Blocks are the Interface
@tarendai https://tomjn.com
@tarendai https://tomjn.com wp.blocks.registerBlockType( 'tomjn/helloworld', { title: 'Hello World', icon: 'universal-access-alt',
category: 'layout', edit() { return el("p", "Hello World, step 1 (from the editor)."); }, save() { return el("p", "Hello World, step 1 (from the frontend)"); }, } );
@tarendai https://tomjn.com
@tarendai https://tomjn.com
@tarendai https://tomjn.com Building a Block Editor Component
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { return <div
className="editor-styles-wrapper"> .... </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com function Editor({ startingContent, inputName }) { const [
blocks, update ] = React.useState( parse(startingContent) ); return <div className="editor-styles-wrapper"> <BlockEditorProvider value={blocks} onInput={update} onChange={update}> <WritingFlow> <ObserveTyping> <BlockList /> </ObserveTyping> </WritingFlow> <Popover.Slot /> </BlockEditorProvider> <input type="hidden" name={inputName} value={serialize(blocks)} /> </div>; }
@tarendai https://tomjn.com
@tarendai https://tomjn.com Building a Generic JS Function
@tarendai https://tomjn.com tomjn_wp_editor( 'The ID of the tag', 'The desired
input name', 'Starting content' );
@tarendai https://tomjn.com
@tarendai https://tomjn.com window.tomjn_wp_editor = function( id, inputName, content ) {
const element = document.createElement( 'div' ); element.setAttribute( 'class', 'tomjn_editor_container block-editor gutenberg__editor' + 'block-editor__container' ); element.setAttribute( 'id', id ); document.getElementById( id ).replaceWith(element); ReactDOM.render( <Editor startingContent={content} inputName={inputName} />, element ); }
@tarendai https://tomjn.com window.tomjn_wp_editor = function( id, inputName, content ) {
const element = document.createElement( 'div' ); element.setAttribute( 'class', 'tomjn_editor_container block-editor gutenberg__editor' + 'block-editor__container' ); element.setAttribute( 'id', id ); document.getElementById( id ).replaceWith(element); ... }
@tarendai https://tomjn.com ... ReactDOM.render( <Editor startingContent={content} inputName={inputName} />, element );
}
@tarendai https://tomjn.com Commenting
@tarendai https://tomjn.com var allowedBlocks = [ 'core/paragraph', 'core/image', 'core/html', 'core/freeform'
]; wp.blocks.getBlockTypes().forEach( function( blockType ) { if ( allowedBlocks.indexOf( blockType.name ) === -1 ) { wp.blocks.unregisterBlockType( blockType.name ); } });
@tarendai https://tomjn.com Building a Generic PHP function
@tarendai https://tomjn.com
@tarendai https://tomjn.com <?php wp_editor( $content, $editor_id, [] ); ?>
@tarendai https://tomjn.com <?php wp_block_editor($content, $name); ?>
@tarendai https://tomjn.com <?php function wp_block_editor( $content, $name ) { ?>
<input name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $name ); ?>" type="hidden" /> <script> document.addEventListener('DOMContentLoaded', function(event) { tomjn_wp_editor( '<?php echo esc_js( $name ); ?>', '<?php echo esc_js( $name ); ?>', '<?php echo esc_js( $content ); ?>' ); }); </script> <?php }
@tarendai https://tomjn.com Supporting PHP Code
@tarendai https://tomjn.com 1. setup the core data layer 2. enqueue
styles and scripts
@tarendai https://tomjn.com $wp_scripts->registered['wp-data']->extra['after'] = array(); wp_add_inline_script( 'wp-data', implode( "\n", [
'( function() {', ' var userId = ' . get_current_user_ID() . ';', ' var storageKey = "WP_DATA_USER_" + userId;', ' var persistence = wp.data.plugins.persistence', ' wp.data.use( persistence, { storageKey: storageKey } );', ' persistence.__unstableMigrate({ storageKey: storageKey });', ' wp.data.use( wp.data.plugins.controls );', '} )();', ]) );
@tarendai https://tomjn.com wp_enqueue_script('wp-editor'); wp_enqueue_script('wp-core-data'); wp_enqueue_script('wp-data'); wp_enqueue_script('wp-block-library'); wp_enqueue_script('wp-format-library'); wp_enqueue_style('media'); wp_enqueue_style('l10n'); wp_enqueue_style('buttons');
wp_enqueue_style('wp-editor');
@tarendai https://tomjn.com I'm Tom J Nowell @tarendai https://tomjn.com WordPress VIP
@tarendai https://tomjn.com https://wpvip.com/careers
@tarendai https://tomjn.com
@tarendai https://tomjn.com