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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
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
97
REST APIs for Absolute Beginners
tarendai
0
1k
VVV 2
tarendai
0
880
WordCamp Europe 2016 - Handling Anxiety
tarendai
1
580
Escape From New York
tarendai
0
820
WP The Right Way
tarendai
0
1.1k
Code Deodorant 2014
tarendai
1
820
Adv WP CLI
tarendai
0
780
WP CLI
tarendai
0
750
Other Decks in Technology
See All in Technology
AI時代の開発生産性は、個人技からチーム設計へ
moongift
PRO
4
2.4k
Type-safe IaC for Dart
coborinai
0
160
「守りたい体験」を渡すだけで E2E を生成させられるようになった話
hinac0
0
180
大量データに対しても、生成AIを用いてリーズナブルにデータ加工をしたい!Databricksのai_queryについて調べてみた
kamoshika
1
220
オブザーバビリティ、本当に活用できてる? 〜API連携×生成AIで成熟度を自動評価〜
dmmsre
1
3.5k
「早く出す」より「事業に効く」 ── 顧客の業務サイクルから逆算するAI時代の二重ループ開発と「変化の設計者」 / devsumi2026
rakus_dev
1
370
SREとQA 二人三脚で進めるSLO運用/sre-qa-slo
sugitak
0
860
Network Firewallやっていき!
news_it_enj
0
170
Empower GenAI with Agile - あなたのアジャイルが生成AIのバフになる仕組み
hageyahhoo
1
210
AI、CDK と協働する Full TypeScript アプリケーション開発 / Full TypeScript Application with AI and CDK
geekplus_tech
2
380
そのドキュメント、自動化しませんか?
yuksew
1
300
SoccerMaster: A Vision Foundation Model for Soccer Understanding
kzykmyzw
0
140
Featured
See All Featured
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
23k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.3k
Accessibility Awareness
sabderemane
1
160
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Deep Space Network (abreviated)
tonyrice
0
230
A Soul's Torment
seathinner
6
3.1k
Product Roadmaps are Hard
iamctodd
55
12k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
Bash Introduction
62gerente
615
220k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
1
2k
Designing for Performance
lara
611
70k
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