Code Amp https://codeamp.com/ Developing WordPress Plugins Sun, 03 Mar 2024 11:56:59 +0000 en-GB hourly 1 https://wordpress.org/?v=6.9.1 https://codeamp.com/wp-content/uploads/2018/08/cropped-logo-150x81.png Code Amp https://codeamp.com/ 32 32 Using PHP namespaces in WordPress plugins + creating an autoloader https://codeamp.com/using-php-namespaces-in-wordpress-plugins-creating-an-autoloader/ https://codeamp.com/using-php-namespaces-in-wordpress-plugins-creating-an-autoloader/#comments Thu, 19 Aug 2021 10:27:48 +0000 https://codeamp.com/?p=502 I’ve been working on upgrading one of my WordPress plugins – Search & Filter for some time now, quite the overhaul you might say… When planning this update there were a bunch of things I knew I needed to implement. I won’t bore you with all the details, but two tasks I wanted to tick […]

The post Using PHP namespaces in WordPress plugins + creating an autoloader appeared first on Code Amp.

]]>
I’ve been working on upgrading one of my WordPress plugins – Search & Filter for some time now, quite the overhaul you might say…

When planning this update there were a bunch of things I knew I needed to implement. I won’t bore you with all the details, but two tasks I wanted to tick off were:

  1. Use PHP namespaces
  2. Setup an autoloader

PHP namespaces

The plugin is getting quite big, and having everything as a class with a unique name was getting a bit messy.

PHP namespaces solve this issue perfectly as you can scope your classes and then you only need to worry about the uniqueness of your top-level namespace (uniqueness is important in WP plugins in order to avoid conflicts with other plugins).

This also lends itself very nicely to consistent project structure because you will likely nest your files in directories matching your namespaces – everything becomes more predictable and uniform.

PHP autoloader

When PHP applications grow in size, rather than having to require every other .php file in a long list (or by some other method) it’s good practice to automatically load them.

As long as your application has a predictable structure (namespace and class names), you don’t need to specify which files to load because we can predict where the relevant file is for a particular class (more on that later).

What’s also great about autoloaders is they only load files at the last minute – when a class is used – giving your application a lighter memory footprint.

These two concepts absolutely go hand in hand.

WordPress enters the room…

Ok, so we know from the above that if our plugin is going to grow that we’re going to want to use both namespaces and an autoloader.

And if we’re good developers, we also want to follow the WordPress coding standards.

Coding standards are a good thing and often in the life of a developer, we’ll find conflicting scenarios where we might want to use one set of standards or the other.

The problem here is, while WordPress coding standards cover a lot they don’t mention anything about namespaces.

I’ve read a few articles similar to this on ways to use autoloading with WordPress like this one and this one – and I’m going to share my take on a possible setup.

There is no mention of namespaces in the docs which leaves this wide open to interpretation and using our best guess – this post is my best guess as to what I think the WordPress way could be.

WordPress PHP Coding Standards

In the naming conventions, it’s stated that class names should be cased like this:

My_Class

And that they should have a corresponding filename something like this:

class-my-class.php

The class name is lowercased, underscores are hyphenated and the filename is prepended with class-.

So far so good.

Plugin Development Best Practises

There is a section in the best practises which is hugely important:

Prefix everything!

When a site can have hundreds of plugins, the only way our code won’t be messed with is if we prefix everything (including class names).

You might want to go with a simple abbreviation prefix, eg, if your plugin was called Speed Up, you could use SU_My_Class but in my opinion (and in the examples) the full name is better, so in theory, the ideal class name would be:

Speed_Up_My_Class

It’s already getting ugly, but it is necessary.

This would ideally be in a file:

class-speed-up-my-class.php

Switching to namespaces

When structuring a plugin like this it is common to find yourself with tons of files starting with class-speed-up-... .php – to me it’s ugly, but it’s necessary because it accurately represents the class name, which has been prefixed too Speed_Up_...

If we switch to namespaces we can alleviate some of this pain and repetition:

namespace Speed_Up;

class My_Class {

}

The great thing here is, now My_Class lives inside the Speed_Up namespace, we don’t need to worry about prefixing it with Speed_Up again. By using a namespace, we’ve kind of prefixed everything inside of it automatically and it won’t conflict with other plugins.

This is how we would use the class now:

$my_class = new \Speed_Up\My_Class;

So I think there is not much complexity in this process – just start using them and drop the plugin prefix from all your class names (and filenames) – to be honest I think it’s keeping in line with the spirit of prefix everything.

*Also – I haven’t mentioned it explicitly – in my opinion, the naming convention of the namespace should match that of a class, with underscores separating words with initial capital letters.

A quick note about namespaces – they support nesting! So you can keep adding names spaces and sub-levels to improve your code organisation – eg:

Speed_Up\Frontend\Scripts\Register

Setting up the autoloader

Now we’ve got the namespace out of the way let’s head back to the autoloader.

There are a few ways to setup autoloaders (each with its own unique benefits) which I’m not going to get into right now – I’m going to go for the easiest and most straightforward method while also keeping things in the spirit of the WordPress coding standards.

Setting one up requires using built-in PHP features.

To implement this in a plugin would require adding some code at the top of your plugins main php file – if we’re sticking with the name speed-up then it would be located:

wp-content/plugins/speed-up/speed-up.php
  • We could also create a new file autoload.php in the root directory to store our autoloader – which is something you’ll probably see quite often when reading up on the subject. *

If we add the first example from the PHP docs:

spl_autoload_register(function ($class_name) {
    include $class_name . '.php';
});

Then we’ll be all set to go! Well, kind of.

What this code does is register a callback to be used, to specify which filename/path we should look in order to find a class.

Roughly how it works:

When a class is first used, eg: $my_class = new My_Class() and it is not yet loaded, the function we passed to spl_autoload_register will be run to try to resolve the filename for the class.

It is passed in the $class_name, and then you can see the file is loaded via include. In the example above, based on the class name the file

My_Class.php would attempt to be loaded.

Also, something worth observing, when a class is used in a namespace, the full namespace + class name is passed through $class_name.

Writing an autoloader for a WordPress plugin

So let’s apply the coding standards to the autoloader and calculate the correct file path based on namespace and class name.

What we want to achieve:

  • Class filenames must be prefixed with class-
  • Class filenames should be lowercase
  • Underscores should be replaced with dashes

And we’re going to convert namespaces. Classes belonging to a namespace should live in a folder (namespace name) that follows the conversion process of a class. So we need to add:

  • Namespace names will be converted to lowercase
  • Namespace names will have underscores replaced with dashes
  • Namespaces will be folders so convert \ to a directory

In addition – because the root plugin folder “is the plugin” and already has a directory name relevant to the plugin name, eg – speed-up we shouldn’t create another folder called speed-up just to match our Speed_Up plugin namespace, it’s unnecessarily repetitive and we’ll actually remove that, and instead, we’ll create a folder called includes for our classes instead.

So our plugin structure would look like this:

speed-up // top-level plugin folder
-- speed-up.php // main plugin file
-- readme.txt // required with every plugin
-- includes // this folder is where we store all our classes
---- database // folder for the sub namespace Database
------ class-connect.php // class Connect
       class-worker.php // class Worker

The class Worker in includes\database\class-worker.php above would be accessed like this:

Speed_Up\Database\Worker

For me, this is the perfect balance of adding namespaces to WordPress plugins while keeping in the spirit of the coding standards.

The code

To parse the name space and class names, and follow those above conversion rules (class name -> path + filename) would result in some PHP code like this:

// Define the main autoloader
spl_autoload_register( 'speed_up_autoloader' );
function speed_up_autoloader( $class_name ) {

    // These should be changed for your particular plugin requirements
    $parent_namespace = 'Speed_Up';
    $classes_subfolder = 'includes';

    if ( false !== strpos( $class_name, $parent_namespace ) ) {
        $classes_dir = realpath( plugin_dir_path( __FILE__ ) ) . DIRECTORY_SEPARATOR . $classes_subfolder . DIRECTORY_SEPARATOR;

        // Project namespace
        $project_namespace = $parent_namespace . '\\';
        $length = strlen( $project_namespace );

        // Remove top-level namespace (that is the current dir)
        $class_file = substr( $class_name, $length );
        // Swap underscores for dashes and lowercase
        $class_file = str_replace( '_', '-', strtolower( $class_file ) );

        // Prepend `class-` to the filename (last class part)
        $class_parts = explode( '\\', $class_file );
        $last_index = count( $class_parts ) - 1;
        $class_parts[ $last_index ] = 'class-' . $class_parts[ $last_index ];

        // Join everything back together and add the file extension
        $class_file = implode( DIRECTORY_SEPARATOR, $class_parts ) . '.php';
        $location = $classes_dir . $class_file;

        if ( ! is_file( $location ) ) {
            return;
        }

        require_once $location;
    }
}

I’ve also setup a tiny demo plugin using the above for you to play with over on GitHub:
Github Repo

If you want to read more articles like this you can follow me on Twitter to keep up to date.

The post Using PHP namespaces in WordPress plugins + creating an autoloader appeared first on Code Amp.

]]>
https://codeamp.com/using-php-namespaces-in-wordpress-plugins-creating-an-autoloader/feed/ 3
Update: Custom Layouts 1.3.0 https://codeamp.com/update-custom-layouts-1-3-0/ https://codeamp.com/update-custom-layouts-1-3-0/#comments Tue, 16 Mar 2021 09:37:42 +0000 https://codeamp.com/?p=407 This one is a bit of a special release. While previous versions have mostly revolved around improving the admin UI and workflow, this release aims to add features that open up a ton of options for creating dynamic templates. The driving force behind all this you (didn’t) ask? New template elements 1. Custom Field This […]

The post Update: Custom Layouts 1.3.0 appeared first on Code Amp.

]]>
This one is a bit of a special release.

While previous versions have mostly revolved around improving the admin UI and workflow, this release aims to add features that open up a ton of options for creating dynamic templates.

The driving force behind all this you (didn’t) ask?

New template elements

1. Custom Field

Custom Field Element Insepctor

This supports native WordPress Custom Fields and has 3 formatting options:

  • Text – display the Custom Field as is, or restrict its length by number of words / characters, add a custom ellipsis.
  • Number – format to number of decimal places (up to 4), choose custom comma and period characters for i18n
  • Date – Dates can be formatted according to a few preset options as well as allowing custom formatting

We also wanted to put a bit of extra effort into making this control easy to use – so we’ve opted to use a customised autocomplete control for choosing your custom field key – that means you can copy and paste your custom field names (for power users), but you’ll also get a suggestion box to help you choose your custom field more easily.

Advanced Custom Fields + Pods users – custom fields for both plugins are supported, but currently these are only single value custom fields (ie, where a custom field has a string, date or numeric value). We will be improving integration with this (I’m looking at you relationship + repeater fields 👀) – for now, you can always use their respective shortcodes in our new text element.

2. Taxonomy

This one we wanted to ship with release, but it proved to be a bit more tricky to implement.

You can now select any taxonomy, or combination of taxonomies and then merge the terms together as one list – you can use multiple taxonomy elements in a template and seperate them out. There are also design controls for the individual taxonomy terms – so you can completely customise the look and feel of this element.

3. Text

Well this is a simple one, its a plain text box to enter text… ahem… and it’s not even Rich Text (that’s coming)… But what makes this powerful is it also supports shortcodes.

This means you can hook in any shortcode here and start extending.

An example using Custom Field, Taxonomy + Text Elements

More CSS units / better at responsive

We’ve upgraded some admin controls to use the Gutenberg BoxControl Component. This means, for margin, padding and border radius, across all elements, you can now use additional CSS unit types, independently for each value:

  • px
  • %
  • rem
  • vh
  • vw

This opens up a ton of design possibilities and allows for better responsive designs – we finally have scalable units.

Toolbar Button – Full width / auto width

We’ve added a new toolbar button for most element types. This sets the container width to wrap around the content, or to fill the available width of the template – you will see the effect on any elements that have a background color applied.

That’s it for now – I think we’ve covered the main changes in version 1.3.0.

What would you like to see next?

Some ideas floating around at the moment:

  • Website, demos, docs (these are coming very soon)
  • Modernise the admin UI (don’t use classic post meta boxes when editing templates)
  • Onboarding – make it easier to understand how everything works together (welcome screen?)
  • Make our Template Elements available as blocks for FSE
  • Make Blocks available in our Template Editor
  • Elements for rows + columns

All the things on the roadmap:

  • Improve performance and load speed by providing an option to use CSS Grid for layouts + masonry
  • Support additional CSS unit types in more places
  • Elements for WooCommerce
  • Elements for ACF
  • More layout elements (possibly use the block library)
  • Additional hover options
  • Additional font options – either Google fonts or the Gutenberg api which looks like it’s coming soon
  • Social/sharing elements

The post Update: Custom Layouts 1.3.0 appeared first on Code Amp.

]]>
https://codeamp.com/update-custom-layouts-1-3-0/feed/ 11
A Gutenberg MultiSelect component https://codeamp.com/a-gutenberg-multiselect-component/ Wed, 27 Jan 2021 11:50:29 +0000 https://codeamp.com/?p=390 This is a little adaptation of the FormTokenField found in Gutenberg core. Working on the Custom Layouts plugin, I needed a multiselect for it’s layout block and editor options. There are some cool controls already in Gutenberg for selecting a page, or choosing tags, but they are not actual multiselect – that is, a set […]

The post A Gutenberg MultiSelect component appeared first on Code Amp.

]]>

This is a little adaptation of the FormTokenField found in Gutenberg core.

Working on the Custom Layouts plugin, I needed a multiselect for it’s layout block and editor options.

There are some cool controls already in Gutenberg for selecting a page, or choosing tags, but they are not actual multiselect – that is, a set of options presented to the user to choose from, and the ability to select multiple (this is just my opinion, not definition…).

The existing compontents require search/input before displaying options, whereas I wanted to show all options on interaction. While I can see it is not planned to add this into the current components system, I think it will be covered by G2 Components – so consider this a filler, until that time.

You can get the source code here.

I hope you will find it handy – happy coding (and hurry up G2, thanks…)

The post A Gutenberg MultiSelect component appeared first on Code Amp.

]]>
Creating the Custom Layouts plugin https://codeamp.com/creating-the-custom-layouts-plugin/ https://codeamp.com/creating-the-custom-layouts-plugin/#comments Sun, 03 Jan 2021 18:57:47 +0000 https://codeamp.com/?p=339 So I thought I’d write a post about a project I’ve been working on, a new plugin – Custom Layouts. The plugin offers some familiar features that you’ve seen before, packaged in themes or available in a myriad of plugins free and paid for.. that is:

The ability to display posts or products, in a list or grid...

The post Creating the Custom Layouts plugin appeared first on Code Amp.

]]>
For those interested – this is how and why this plugin came to be. If you’re looking for the docs – they’re being written – link coming soon.

So I thought I’d write a post about a project I’ve been working on, a new plugin – Custom Layouts.

The plugin offers some familiar features that you’ve seen before, packaged in themes or available in a myriad of plugins free and paid for.. that is:

The ability to display posts or products, in a list or grid

So why did I decide to create the same thing that’s been done many times over before? Let’s cover a bit of background.

The Background

This plugin started as a feature idea for another plugin I develop (Search & Filter). That plugin allows you to create filters on the frontend of your site, so your users can find the content they are looking for.

Since the early days of developing Search & Filter, our users have been asking us how to customize the results/layouts. Our approach has been to integrate with some of the excellent themes and plugins out there (and for developers, there are plenty of options built-in)…

But we always found scenarios where our users couldn’t use a provided integration, or didn’t want to buy into a whole ecosystem to customize a layout, or, wanted to use a plugin that we didn’t yet provide an integration for.

So it seems the best way to serve our users is to offer these features in some shape or form as a “catch-all”. An option for our users who couldn’t use the other offerings – or even eventually as a preferred option.

To create a feature or a new plugin?

As a set of features

Although this where the idea/requirement came from, this option I preferred less.

  • Having this hidden as a sub-feature of another product is not doing all that functionality and time invested, justice.
  • It will add bloat (many people will not need it) to the Search & Filter plugin
  • Limited exposure to the existing user base of the filter plugin

As a plugin

This seemed to be the right direction. If we’re going to build something well, with a decent set of features, then it makes sense to manage it on its own.

Not only that, but it’s clear there is a huge market for these kinds of plugins. It can stand on its own and there would be plenty of people (I hope) wanting to use this standalone.

We would then benefit from added traffic/sales to Search & Filter via users of this new plugin – bonus 🙂

And what about a premium version? For now, this doesn’t interest me. The idea is not to be the most comprehensive offering on the market – or to cater to a niche (good reasons to put a price tag on).

I like the idea of creating something and giving it away (and let’s be honest, this option still has it’s benefits) – I’ve personally gained so much from the WordPress ecosystem and I’ve given back here and there, but I think this could be a more substantial contribution.

Requirements

So what started out as a feature idea for a premium plugin, turned out to be a fully-fledged project of its own. With this came a new set of requirements and considerations:

  1. Allow users to build highly customized layouts for lists/grids of posts
  2. Integrate seamlessly with our existing plugin Search & Filter Pro
  3. Be incredibly easy to use
  4. Improve on the existing offerings (if we’re going to build something that’s been built many times before, we really should have some good reasons to do so – such as improving features/ease of use is a good enough excuse for me)
  5. Work well in as many installs/environments as possible (as is the nature of building a plugin for the plugins repo)

Improving on existing solutions

To be honest there are so many great options and there’s really nothing obvious that stands out. However, I have identified one area I think is a common pain point for most existing solutions – a cluttered UI.

Problems with a cluttered UI

In order to offer more features to the user, all solutions must provide more options (generally speaking)… In the era of page builders and WYSIWYG editors, current solutions are in general, fantastic. But many suffer from the same thing – adding hundreds (well maybe not that many) of customization options, in 1 sidebar/panel (ala Gutenberg + Elementor plugins) or adding too many options to the block toolbar.

Posts Block from the WP.com Editing Toolkit
Sorry Automattic – there’s actually nothing wrong with this… (yet?)

So there are two ways I think most offerings are going: add more features and clutter the UI, or limit features and improve the editing experience (by the way I’m not advocating that more options are always better, but in some use cases you really do want to offer more features but can’t).

In the example above, I think we’re already reaching a critical point in terms of offering options to the user – there are certainly enough toolbar options, and while the sidebar has been carefully managed to not be too overwhelming, you can easily see that if we want to start adding individual options for things like the post title, author section – then it’s going to start affecting the user experience.

Anyway, for this particular plugin, I’d rather not choose – I want to offer more options and I want it to be easy to use (I’m demanding)… The good thing is, I think this problem has already been solved for us – in the page builders themselves!

They are the best examples of increasing complexity + features whilst also improving the user experience.

So why not bring the “page builder” paradigm one level deeper into this plugin?

Another layer of abstraction

In my opinion, there is a clear separation between the list/grid layout and the design of each individual item/result.

* There has always been a clear separation of these two areas in WordPress itself and may be better known as “the loop” and “template part”.

Grid/Layout Vs Post Template

If we separate the two, we achieve 2 things:

  • A higher degree of customizability with the individual item/template
  • Simplify the process of adding a layout/grid/list and declutter this experience

The solution: separate the layout from the post template

That’s it – we should provide a visual page builder type solution to building layouts and templates, but, not together in the same widget/block…

Cue the Custom Layouts plugin 🙂

Implemenation (+ Gutenberg)

So there could be a few approaches to create something like this while ticking off the requirements:

Using the Block Editor as the foundation

I thought about the potential to use Blocks for the layout, and InnerBlocks for the post templates – I’m not 100% that this is the easiest way to do this for user experience – nor is the implementation (as far as I can tell) of InnerBlocks mature enough to build upon – I’d rather wait a little while (and learn a bit more)…

This option also has the huge caveat of forcing the plugin to be available to Block Editor users only.

Building a custom solution

The way forward I felt is to create something that works well on its own (so it works for everyone) and then from there consider how to integrate that with the block editor for a better user experience/workflow (it’s the future, by the way 😉 ).

The solution:

  1. Regular WordPress CPT’s are registered for layouts + templates
  2. These CPTs will have custom React Apps for building layouts + templates using a drag and drop interface – we use 90% Gutenberg components for building the UI, so everything looks and feels like WordPress (and so it also works incredibly well)
  3. Layouts are made available via shortcodes for any WP install so can be placed anywhere
  4. After this, we tightly integrated our layouts + template editor with the Block Editor by adding a layout block, and linking that with the template editor via a modal, so you never have to leave the editing experience

* Block Editor users – one thing I would say, that while offering a modal for the template editor is a pretty cool experience (stops you from navigating away from the editor) – I’m not 100% sold on if that is the best way to achieve this – it’s a work in progress.

** Also, all modals in the Block Editor are subject to some buggy behaviour – the editor captures keyboard shortcuts and makes changes to the document underneath.

Benefits

So, using this approach now means several things:

  1. The layout + template editors are available to all WordPress users no matter your choice of editing experience.
  2. It’s much easier to change what you want – clicking on the post title to bring up the post title options seems much more natural in the template editor rather than burying the options in a panel in a sidebar of a layout.
  3. We get to (once again) overload the user with options ^^ – well, hopefully not, but we can offer more “sub-options” (ie options for the post title, featured image, etc) more easily now, and they are less confusing + easier to locate.
  4. Layouts also become simpler to use – they consist of only a few settings, query-related, layout related, and choosing a post template – gone is the overhead of all those options cluttering the sidebar unless you choose to drill down into it.
  5. Templates and layouts are re-usable – so you can update the template once and see changes reflected across the site. If you are using the Block Editor, you can create a re-usable block for much the same effect. I do see some cross over functionality here which I’m sure will be refined over time.

So there you have it, the making of, so to speak…

After thoughts

This plugin has essentially been the product of 1.5 years of learning React + Gutenberg – and 4 months building this plugin.

I have to say, working with Gutenberg and the Block Editor as a developer is a far superior experience to the old paradigm (the classic editor) – the learning curve is definitely greater, but once you get over the hump it seems the future is bright.

I also love the fact that we don’t actually need to be using the Block Editor to use Gutenberg components – that means we can still build what we want and how we want it (providing we’re using React), whilst keeping the UI in tune with the rest of WordPress.

Saying that, I have experienced some friction with using Gutenberg components in custom React apps – but I’m assuming that will reduce over time.

And it look’s like there are already some developments coming with the g2 components which may resolve some of these pain points – due to better standardization across components.

Anyway, that’s it for this post – if you’ve made it down here, thanks for reading, and let me know your thoughts 🙂

Get the Custom Layouts plugin from the plugins repo

The post Creating the Custom Layouts plugin appeared first on Code Amp.

]]>
https://codeamp.com/creating-the-custom-layouts-plugin/feed/ 5
Interacting with Gutenberg’s RichText Component https://codeamp.com/interacting-with-gutenbergs-richtext-component-using-a-button/ https://codeamp.com/interacting-with-gutenbergs-richtext-component-using-a-button/#comments Thu, 23 Aug 2018 13:16:44 +0000 http://codeamp.com/?p=156 …by inserting a shortcode (using a button). As of the latest WordPress update we all now know about the Gutenberg editor, and whether you love or hate it, it’s here to stay. But, as it’s so new, it means the APIs are still being worked on – which (naturally) means some things are just not […]

The post Interacting with Gutenberg’s RichText Component appeared first on Code Amp.

]]>
…by inserting a shortcode (using a button).

As of the latest WordPress update we all now know about the Gutenberg editor, and whether you love or hate it, it’s here to stay.

But, as it’s so new, it means the APIs are still being worked on – which (naturally) means some things are just not possible or documented yet.

That being said, there are plenty of great resources out there at the moment for creating Gutenberg Blocks.  This post assumes you know how to:

  1. Create a Gutenberg Block Plugin
    ~ check out create-guten-block
  2. Add Toolbars to Blocks
    official docs have got you covered
  3. Add the RichText component to a Block
    ~ check out the excellent video by Zac Gordon

The Problem

What if we want to make a word red, or add a shortcode into our RichText Component with a single click? …and how about from a button on the toolbar?

Sure, we can roll our own and create any kind of editor in our block (we have total flexibility to integrate TinyMCE however we want), but surely there’s a way to do it with the built in RichText component… After all its what the core blocks use, and we like doing things the WP way right?

This is something that all my googling couldn’t unearth…

After some days digging around and a lot of hacking at code I’ve found there is indeed a way.

The Solution

Before we get to that, lets get up and running with some familiar Gutenberg Block code.

1.  Create a Block with RichText and BlockControls (Toolbar) Components

This post assumes you already know how to create a Gutenberg Block with a RichText component. If not, you should familiarise yourself with the resources above.  Your code should look something like this:

View the Code

Nothing out of the ordinary – we’re using registerBlockType to setup our block, adding RichText and  BlockControls components to our edit function, with a couple of functions handling the changes and setting the content.

If you’re using create-guten-block, then replace src/block/block.js with the above Gist.

2. Accessing the editor

Using `onSetup`

Although it’s not documented yet we can see onSetup is a callback we can utilise which will return a copy of the TinyMCE editor (RichText components use TinyMCE).  However for me at least this was not the tricky part.

Disclaimer: I’m pretty new to React + ES6 and still getting my head around some of their concepts – which is probably why I found this more difficult to understand than some might.

My first idea was to setup a callback which receives the TinyMCE editor, and then stores a reference to that in the current object:

function onEditorSetup( editor ) {
    this.editor = editor;
}

Fail… What’s wrong with this?  …Scope.

One thing I’ve learnt is, the edit function is returned for each instance of our block in the post editor view, but the parent object with the edit function is invoked only once when setting up the block as a block type (should be pretty obvious really, took me a minute).

This means that anything we want to use in our edit function, must live only inside the edit function (pretty much) so that each instance is self contained, and interacts with its own objects…

Hmm… Where to go from here… where do we store the reference to editor?

Extending the `edit` function

If edit is a function, then I could see no reliable way to keep track of each instance of our editor and controls. I did think about wrapping RichText in a React Component so I could keep a reference to the editor, within a certain scope, but then realised that I’d run in to the same problem when trying to get the toolbar button to interact with it. It was a bit beyond me.

Cue examining the Gutenberg source code (again). Sure enough, there is a Gutenberg component that utilises the onSetup callback and provides a great example of how to handle this scenario correctly.

Turns out my thinking was a bit limited, what I needed to understand was that edit just needs to return a React Component.

So what they’ve done with the List Component is create a React Component on edit, and return the RichText and all the trimmings together within the Component, so they can access shared local variables, functions etc.

Great stuff, this means we can get our button talking to the editor within the same scope.

Lets see what edit might look like, using inspiration from the Gutenberg source (check the inline comments):

edit: class extends Component {
    
    //standard constructor for a component
    constructor() {
        super( ...arguments );
        
        //make sure we bind `this` to the current component within our callbacks
        this.setupEditor = this.setupEditor.bind( this );
        this.onChangeContent = this.onChangeContent.bind( this );

        this.state = {
            //we don't need our component to manage a state in this instance
        };
    }
    
    //same as before, except `this` actually references this component
    setupEditor( editor ) {
        this.editor = editor;
    }
    
    //no change here again, except the binding of `this`
    onChangeContent( newContent ) {
        this.props.setAttributes( { content: newContent } );
    }
    
    //slightly different pattern of syntax here, we're returning a function
    onClickShortcodeButton() {
        return () => {
            
            //the content we want to insert
            var myContent = '[myshortcode][/myshortcode]';
            
            if ( this.editor ) {
                //execCommand is a TinyMCE function
                this.editor.execCommand( 'mceInsertContent', false, myContent );
            }
        };
    }
    
    //all react components require render - this is what will be returned by our component
    render() {
        const {
            attributes,
            setAttributes,
            className,
        } = this.props;
        
        return (
            <Fragment>
                <BlockControls
                    controls={ [
                        {
                            icon: 'edit',
                            title: __( 'Insert Shortcode' ),
                            onClick: this.onClickShortcodeButton(),
                        },
                    ] }
                />
                <RichText
                    //getSettings={ this.getEditorSettings } //a useful callback for adding params to TinyMCE on setup
                    onSetup={ this.setupEditor }
                    key = { 'editable' }
                    tagName = { 'p' }
                    className = { className }
                    onChange =  { this.onChangeContent }
                    value = { attributes.content}
                />
            </Fragment>
        );
    }
},

Remember edit is now a React + ES6 Component, so the syntax is fairly standard, but not what you might be used to seeing in a Block.

What we’ve done here is port everything (our click handlers, return elements) over so that it uses the correct syntax/structure for a React Component.  One thing to note is, if we’re using a React Component it must properly return the Component in the render method, which looks a lot like the return of our old edit function.

There is one addition though, now that we have this.editor working within the scope of the Component, I’ve added the final functionality allowing the button to interact with it:

onClickShortcodeButton() {
	return () => {
		
		//the content we want to insert
		var myContent = '[myshortcode][/myshortcode]';
		
		if ( this.editor ) {
			//execCommand is a TinyMCE function
			this.editor.execCommand( 'mceInsertContent', false, myContent );
		}
	};
}

This just updates the click callback to interact with this.editor, and in this case we wanted to insert a shortcode using execCommand.

And that’s it! Everything should be working together nicely now.

From here, the world is your oyster – you have access to the TinyMCE editor which means you can now develop the same functionality into your Gutenberg Blocks as we can with the Classic editor.

NB – you’ll notice in the source a commented getSettings callback, this allows you to modify the settings object that gets passed into TinyMCE when being initialised – might be useful!

Files

View the Final Code

Code as a CGB (create-guten-block) Plugin

Conclusion

There are plenty of possibilities now that we’re able to access TinyMCE in our custom blocks and indeed this will be useful for many right away…

But I’m sure there are a few others thinking, why do all this now? – what we really want to do is add this kind of functionality to the core blocks…! –  and that’s also my thought process…

I think in all likelihood when Gutenberg allows us to extend core blocks, they’re going to have to add a way to access the TinyMCE editors within them, much like when we use onSetup now within our own blocks.

Hopefully, when the time comes and the APIs get updated, we’ll have code that’s pretty much ready to go and had some testing in the Gutenberg  environment at least.

That’s all for now – I would love to hear about things that you’ve made as well as any thoughts on the article.

 

The post Interacting with Gutenberg’s RichText Component appeared first on Code Amp.

]]>
https://codeamp.com/interacting-with-gutenbergs-richtext-component-using-a-button/feed/ 1
Designs & Code will be no more… Long live Code Amp https://codeamp.com/what-happened-to-designs-code/ Wed, 22 Aug 2018 15:43:58 +0000 http://codeamp.com/?p=240 I thought I’d kick off the site with this quick post. A bit of info on what is going on around Designs & Code and Code Amp (short version: we’ve changed name). Essentially, Designs & Code was supposed to be the digital home of the 2 WordPress Plugins I develop. Over time things have changed, one […]

The post Designs & Code will be no more… Long live Code Amp appeared first on Code Amp.

]]>
I thought I’d kick off the site with this quick post.

A bit of info on what is going on around Designs & Code and Code Amp (short version: we’ve changed name).

Essentially, Designs & Code was supposed to be the digital home of the 2 WordPress Plugins I develop.

Over time things have changed, one of the plugins has it’s own website now – searchandfilter.com, and the other will shortly follow.

In tandem, while we’ve grown and given our plugins their own homes, I’ve also formed a UK Limited company to handle the business end of our Pro plugins – Code Amp.

In lieu of the above, Designs & Code will be retired, and rather than have a boring company profile / website here I thought I’d do what I’ve wanted to do for some time – start a tech blog based around coding and WordPress.

…and there you have it, straight forward really – and just to clarify, nothing else has changed behind the scenes – its still me, Ross, running the shop.

That’s all for now, my next post on Gutenberg and Blocks is following shortly.

Over and out.

The post Designs & Code will be no more… Long live Code Amp appeared first on Code Amp.

]]>