Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
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
1k
VVV 2
tarendai
0
910
WordCamp Europe 2016 - Handling Anxiety
tarendai
1
600
Escape From New York
tarendai
0
830
WP The Right Way
tarendai
0
1.1k
Code Deodorant 2014
tarendai
1
840
Adv WP CLI
tarendai
0
790
WP CLI
tarendai
0
760
Other Decks in Technology
See All in Technology
Code4Lib JAPANカンファレンス2026 開会挨拶 / Code4Lib JAPAN Conference 2026: Opening Remarks
ykiyota
0
240
Bet AI Day 2026丨How We Bet AI: AIとともに働く場をつくる
layerx
PRO
2
2.8k
プロダクト思考 × 基盤思考を AIで実現する Compound Engineering
tkc66buzz
1
290
Amazon Quick on DesktopがIAM Identity Centerで動かない理由
yukiogawa
0
110
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
3
380
Webとヘルスデータ
yukukotani
1
200
日経電子版を支えていく Kasane Design System/fec_fukuoka
nikkei_engineer_recruiting
0
260
#jawssonic2026 あの時代が悪かった ~動かなかったSageMakerと共に迎えたイベント当日~
ktkn1129
0
140
Claude Code本って、 読む必要あるの?
oikon48
1
160
リージョンの壁を越える、 ちょっと変わったAWSサービスの話
falken
PRO
0
270
TinyGo 開発サイクルを高速化する:Go で作るエミュレータ入門
zozotech
PRO
1
130
薬剤師(ドメインエキスパート)と一緒に育てる薬局向けAIアシスタント
kakehashi
PRO
2
120
Featured
See All Featured
From π to Pie charts
rasagy
0
360
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
510
Darren the Foodie - Storyboard
khoart
PRO
3
3.9k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
510
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Side Projects
sachag
455
43k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
530
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
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