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
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
940
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
810
WP CLI
tarendai
0
780
Other Decks in Technology
See All in Technology
Claude Codeから見る、エンジニアの世界の変容とその先
oikon48
7
4.5k
Claude Code on Bedrock で統制をかける小ネタ集/claude-code-bedrock-governance-tips
emiki
1
13k
DevelopersIO 2026 Tokyo 現時点の衛星通信サービスの現状を整理してみる
maroon1st
0
310
顧客価値を追いかけたら、プライシングにたどり着いた
sansantech
PRO
2
1.1k
AI秘書と毎日働くのはもう当たり前。開発以外の業務に足りない機能をどう埋める?
minorun365
PRO
4
1.8k
日本AIベンチャーレポート2026
kentarofujii
0
250
国際カードブランドルール変更に伴うクレジットカード決済取引仕様変更について
k1style
0
240
「社外イベント=意識高い」の壁を壊せ!元々無関心だった僕らが部内で社外イベントを民主化して15人を連れ出すまで
say_no_w
0
160
AWS Continuum for Penetration Testing に Deep Dive してみる
asanoharuki
2
1.4k
How we choose session proposals
kawaguti
PRO
1
180
AI時代の開発はウォーターフォールに回帰する? / development-with-ai-back-to-wf
okamototakuyasr2
0
130
ガチで放置できるClaude Code実行環境の作り方.pdf
lamaglama39
5
9.9k
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
460
Thoughts on Productivity
jonyablonski
76
5.4k
Technical Leadership for Architectural Decision Making
baasie
3
610
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.4k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
3.5k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
Practical Orchestrator
shlominoach
192
12k
WCS-LA-2024
lcolladotor
0
920
AI: The stuff that nobody shows you
jnunemaker
PRO
10
1.2k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
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