Hello understanding designer yellow watermelon!

: Clippy, bash / zsh commands, CSS Color

Gutenberg Dev

Follwing along Zac Gordons Gutenberg Development Course.

Insert:

The Gutenbergs JS libraries

  • wp.element: Abstraction Layer on top of React and React Dom. Used for creating elements inside blocks.
  • wp.blocks: Components and functions for building blocks.
  • wp.components: Components that can be used for building interfaces within the editor (tooltips, buttons … )
  • wp.i18n: For translations, similar to the __() methods in php

All of these libs are accessible globaly (e.g. through the console or other scripts)
To access them within code, use something like

const { __ } = wp.i18n; // using deconstruction

Basic block architecture

Default roadmap:

  1. Enque block JS in main plugin/theme file [php]
  2. Register block using registerBlockType() [js]
  3. Opt. break up block code in components [js]
  4. Enque block css [php]

Enque block js + css

  • enque_block_edtior_assets: hook for enquing block js+css in the editor (not the frontend). Used to enque the main block js file, or editor-only styles.
  • enque_block_assets : hook to enque (mostly) css (and js) for both, the editor and the front endUser for main block styles. Use !is_admin()for front-end-only styles/scripts 

Building blocks

registerBlockType()

wp.blocks.registerBlockType(
  'plugin-name/block-name',
  {
    title: wp.i18n.__('Blocktitle', 'textdomain),
    description: '...',
    category: 'common',
    icon: 'wordpress-alt',
    keywords: [wp.i18n.__('Demo', 'textdomain)],
    supports: { html: false },
    attributes: {} ,
    edit: () => {},
    save: () => {}
  }
);

attributes

Which information to (re-)store and manipulate

attributes {
  message: {
    type: "array",
    source: "children",
    selector: ".classname-of-element"
  },
}

edit

Controls how the block is rendered (and updated) in the editor.
Usualy constists of a return method as well as a method that handles what hapens onChange (e.g. text editing). props ( React, anyone?) are passed on automatically from WP.

edit: props => {
  const {
    attributes: { message },
    className,
    setAttributes
  } = props;
  const onChangeMessage = message => {
    setAttributes({ message });
  };
  return {
    <div className={className}>
      <RichText
        tagName="div"
        multiline="p"
        placeholder={__("Type something ...", "textdomain")}
        onChange={onChangeMessage}
        value={message}
      />
    </div>
  }
}

save

How to save the post – for displaying on the front end and restoring for the editor.

save: props => {
  const {
    attributes: { message }
  } = props;
  return (
    <div>
      <div class="output-feld">{message}</div>
    </div>
   );
}

Update attributes on change

attributes: {
  content: {
    ...
  }
}
edit: props => {
  const { attributes: { content }, setAttributes } = props;
  ...
  return ( 
    <RichText
       ...
       onChange={ content => { setAttributes( { content } ) } }
       value={ content }
    >
);

Data API

wp.data.<STORE_NAME> (stores: „core/editor“, „core/blocks“, „core/editor“ …, to check them out log wp.data.select("<STORE_NAME>") [or dispatch instead of select])
(import: const { <STORE_NAME> } = wp.data)

select

=> get data

select("core/editor").getBlockCount();

subscribe

=> subscribe/listen to status change

subscribe(() => {
  // updated every time the block count changes
  const blockCount = select("core/editor").getBlockCount();
});

Note: subscribe returns a unsubscribe function

const unsubscribe = subscribe(()=>{ /* ... */ });
unsubscribe();

Advanced

Subscribe Class to controll the state handling (otherwise you might want to use withSelect) – more Reactish, less WP abstraction

const { Component } = wp.element;
const { select, subscribe } = wp.data;

    
export default class SubscribeDemo extends Component{

    state = {
        blockCount: "",
    }

    componentDidMount() {
        const unsubscribe = subscribe( () => {
            const blockCount = select("core/editor").getBlockCount();
            this.setState({blockCount});     
        } );
    }

    render() {
        return <p>Block count: {this.state.blockCount}</p>
    }
    
}

Key-Points:

  • Extend the Component class (imported from wp.element)
  • Manage state object ( => React )
    • call with this.state
    • update with this.setState() [see: React]
  • uses componentDidMount()method [see: React]
  • use Reacts render() function

withSelect

=> HOC [?] for select, similar to subscribe it will update everytime its values changes

As component:

const WithSelectDemo = ({ blockCount }) => (
    <p>Block Count: {blockCount}</p>
)
export default withSelect( (select, ownProps) => {
    return {
        blockCount: select("core/editor").getBlockCount()
    }
} )(WithSelectDemo);

Explanation / How to read

First code block: Create <WithSelectDemo /> component that takes the current block count as an argument (and prints it)

Second code block: Export withSelect()(WithSelectDemo):

  • when <WithSelectDemo />is exported/used …
  • it will wrapp everything inside of withSelect()
  • callselect() (getting the block count) …
  • create / asign it to a new variable blockCount
  • and make that variable available to the <WithSelectDemo /> component (which takes it as its argument)

ownProps

Notice the ownProps parameter for the withSelect()above. It will get all props (think: attributes) passed into the component (and can be passed on to the component, of course)

<WithSelectDemo text="blah" />

export default withSelect( (select, ownProps) => {
    console.log(ownProps) // logs: {text: "blah"}
    return {
        ...
    }
...

dispatch

=> calling an action

dispatch( "core/editor" ).removeBlock( clientID ) // clientID = BlockID

withDispatch

=> HOC [?] for dispatch

//TODO

compose

=> HOC [?] for combining multiple HOC’s (Takes an array of HOCs and returns a new component)

// Todo