Skip to content

Instantly share code, notes, and snippets.

@desaiuditd
Last active June 21, 2019 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save desaiuditd/c6ef602b86afa8f22034ab043766517f to your computer and use it in GitHub Desktop.
Save desaiuditd/c6ef602b86afa8f22034ab043766517f to your computer and use it in GitHub Desktop.
Dynamic Template in InnerBlocks
const { Component, Fragment } = wp.element;
// This is going to add block controls to switch the state between preview and search.
import ItemControls from './controls';
// Preview is going to show users how items are going to look like.
import Preview from './preview';
// Search is allowing to search for items.
import Search from './search';
/**
* The Edit Component for the Block.
*
* @export
* @class
* @extends {Component}
*/
export default class extends Component {
/**
* The 2 states in which the Edit component works.
* - Search: Autocomplete functionality to allow users to search for items.
* - Preview: Allow users to preview the item and see how it's going to look like.
*/
editStates = {
preview: Preview,
search: Search
};
constructor() {
super( ...arguments );
const { attributes } = this.props;
const { id: itemId = false } = attributes;
let itemDetails = null;
let editState = 'search';
// Decide whether to show the preview state for the existing item or the search state to add new item. Just check for the ID.
if ( itemId ) {
itemDetails = { ...attributes };
try {
itemDetails.featuredImages = JSON.parse( itemDetails.featuredImages );
} catch ( e ) {
itemDetails.featuredImages = {};
console.log( 'Error in parsing the featured images.' );
}
editState = 'preview';
}
this.state = { editState, itemDetails };
}
/**
* Change the edit state of the Edit component.
*
* @param {String} editState The edit state to be changed to.
*/
switchEditState = editState => this.setState( { editState } );
/**
* Set the asset information to preview for the block.
*
* @param {Object} itemDetails The asset details for the story (id, heading, intro, featuredImage etc.)
*/
setItemDetails = itemDetails => this.setState( { itemDetails } );
/**
* Update the block attributes required to save the item.
*
* @param {Object} prevItem Previous values of item.
* @param {Object} curItem New values of item.
* @returns {null}
*/
updateBlockAttributes( prevItem, curItem ) {
// Bail, if the item is not changed.
if ( prevItem === curItem ) {
return;
}
const { id, heading, intro, featuredImages } = curItem;
this.props.setAttributes( { id, heading, intro, featuredImages: JSON.stringify( featuredImages ) } );
}
/**
* Perform tasks whenever the Component is updated (i.e., either the state or the props are updated)
*
* @param {Object} prevProps Previous values for props.
* @param {Object} prevState Previous values for state.
*/
componentDidUpdate( prevProps, prevState ) {
const { itemDetails: prevItem } = prevState;
const { itemDetails: curItem } = this.state;
// Save attributes.
this.updateBlockAttributes( prevItem, curItem );
}
render() {
const { editState, itemDetails } = this.state;
const StateView = this.editStates[ editState ];
return (
<Fragment>
<ItemControls
editState={ editState }
itemDetails={ itemDetails }
switchEditState={ this.switchEditState } />
<StateView
itemDetails={ itemDetails }
setItemDetails={ this.setItemDetails }
switchEditState={ this.switchEditState } />
</Fragment>
);
}
}
import 'my-custom-block.css';
const { registerBlockType } = wp.blocks;
const { __ } = wp.i18n;
import edit from './edit';
/**
* Register my custom block.
*/
registerBlockType( 'mcb/block', {
title: __( 'My Custom Block' ),
description: __( 'Performing amazing stuff.' ),
icon: 'welcome-add-page',
category: 'common',
/**
* Attributes required.
*/
attributes: {
id: { type: 'string' },
heading: { type: 'string' },
intro: { type: 'string' },
featuredImages: { type: 'string' }
},
/**
* The edit component.
*/
edit,
/**
* The save component.
*/
save: props => ( <InnerBlocks.Content /> )
} );
const {
blockEditor: { InnerBlocks },
i18n: { __, sprintf }
} = wp;
const { getImageURL } = ffx.imageUtils;
/**
* The Preview component for the item.
* Responsible for showing how the item is going to look like.
*
* @export
* @class
* @extends {Component}
*/
export default ( { itemDetails: { id, heading, intro, featuredImages }} ) => {
const imgData = featuredImages[0] || {};
const {
alt,
caption = '',
id,
url
} = imgData;
const template = [
[
'core/image',
{ alt, caption, id, url }
],
[
'core/heading',
{
content: heading,
placeholder: ! heading ? sprintf( __( 'There\'s no heading for this item. ID - %s' ), id ) : undefined
}
],
[
'core/paragraph',
{
content: intro,
placeholder: ! intro ? sprintf( __( 'There\'s no Intro for this item. ID - %s' ), id ) : undefined
}
]
];
const ALLOWED_BLOCKS = [ 'core/paragraph' ];
return (
<div className="ink-blocks-asset-preview">
<InnerBlocks template={ template } allowedBlocks={ ALLOWED_BLOCKS } />
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment