To make things simple, we're going to make a semi-structured way to display a mailing address.
We're going to start with a file tree that looks like this:
address-block
├ blocks
| ├ address.jsx
| └ address.scss
├ address-block.php
└ package.json
One PHP file, one style file, one javascript file, and one file for npm to run the build tools off of.
We're running a fairly clean implementation here -- not too much happening, so let's not overclutter our package.json
{
"name": "address-block",
"scripts": {
"build": "parcel build blocks/address.jsx --out-dir blocks --public-url ."
},
"devDependencies": {
"parcel-bundler": "^1.10.1",
"sass": "^1.15.1"
}
}
For the sake of something here that we can populate later, we're going to add a simple snippet of sass code. This will make sure that new lines on our output will stay as newlines when rendered in html.
.address-block-address {
p {
white-space: pre-line;
}
}
Now, we start building our block javascript. This is, at the moment, a very stripped down version, but that's okay. We'll add to it later.
const {
registerBlockType
} = wp.blocks;
const {
TextareaControl
} = wp.components;
import './address.scss'
registerBlockType( 'address-block/address', {
title: 'Address',
icon: 'sticky',
category: 'common',
attributes: {
address: {
type: 'string',
default: '',
source: 'text',
selector: 'p',
}
},
edit: function( props ) {
return (
<div>
<TextareaControl
label="Address"
value={ props.attributes.address }
onChange={ address => props.setAttributes( { address } ) }
/>
</div>
);
},
save: function( props ) {
return (
<div className="address-block-address">
<p>{ props.attributes.address }</p>
</div>
);
}
} );
Okay, so let's build it, using npm install && npm run build
You should now have three new files, generated by the build script:
address-block
└ blocks
├ address.js
├ address.map
└ address.css
These are the files that we'll be enqueueing to WordPress.
Now, we finally make our main plugin file. We're going to be registering (not enqueueing) our generated style and script files -- and then registering our block type, listing the script and style as dependencies of it, so that they'll get pulled in.
This also means that if some other plugin wants to deregister our block, the scripts and styles won't be loaded. Which is good!
<?php
// Plugin name: Address Block
add_action( 'init', 'register_address_block' );
function register_address_block() {
if ( ! function_exists( 'register_block_type' ) ) {
return;
}
wp_register_style( 'address-block', plugins_url( 'blocks/address.css', __FILE__ ) );
wp_register_script(
'address-block',
plugins_url( 'blocks/address.js', __FILE__ ),
array(
'wp-blocks',
'wp-components',
)
);
register_block_type( 'address-block/address', array(
'editor_script' => 'address-block',
'style' => 'address-block',
) );
}
Your first block is done. Build tools are set up, code is transpiling, all is well!
There's lots more we can do, such as translating the "Address" string in the script, adding a second line for the place name, deep linking to Google Maps to provide directions to the address, dynamically rendering the content -- but for now this is the bulk of the basics.
Not as scary as you thought, right?
This was very helpful, @georgestephanis! Thank you. I used it to create my first blocks: https://github.com/cagrimmett/meta-dates-blocks