Skip to content
This repository has been archived by the owner on May 31, 2021. It is now read-only.

Tutorial Create Custom Team Block

sy4mil edited this page Mar 16, 2013 · 2 revisions

Aqua Page Builder: Creating a custom Team block

Note: This is quite unfinished yet, but I hope could give you some pointers. I originally intended to post this on WPExplorer but haven't really had the time to finish

Since its official release over 3 months ago, Aqua Page Builder plugin has received over 5000 downloads across the globe. If you don't know what Aqua Page Builder (henceforth AQPB) is, then I'd recommend you to watch this short video which demonstrates some of its awesome features. http://www.screenr.com/iI87

Basically, the plugin is a breathe a fresh air for authors & end-users alike who were looking for an extremely intuitive & user-friendly page template builder, without the bloat & seemingly "alien" interface that some of the existing page builders currently have on the market. With AQPB, the whole user experience can simply be described as "being at home with WordPress".

For theme developers, besides being completely free with no strings attached to port this into your commercial themes, one of the most important features of the plugin is its flexibility and extendability. I have been meaning to write a proper article that'd explain more about this feature, but I've been delaying it so that the plugin can grow a little more mature and shave off as many bugs as possible. This article therefore will serve as the first official tutorial which will demonstrate some the awesome features that I've been talking about, in the form a custom block.

In this tutorial, I will demonstrate on how you can build and include your own custom blocks, and define its own custom stylings etc. The custom block which we will be building today is called the "Team Block".

Here's a screenshot of what the end product would look like:

// pic of team block

Before we get started on building our Team block, let's have a look at the base scaffolding of a custom AQPB's block:

class My_Custom_Block extends AQ_Block {

	function __construct() {
		// block actual processes
	}

 	function form( $instance ) {
		// outputs the options form on admin
	}

	function update( $new_instance, $old_instance ) {
		// processes block options to be saved
	}

	function block( $instance ) {
		// outputs the content of the block
	}

}

Seasoned WordPress developers will instantly notice that this structure very closely resembles the WordPress Widget's base structure that they're already familiar with. Similar to WordPress Widgets API, AQPB's Blocks API is basically a PHP Object that contains internal functions and additionally fields helper functions that makes the process of building your own custom block to be systematic and more importantly - symple. Feel free to have a peek at our Wiki(https://github.com/sy4mil/Aqua-Page-Builder/wiki/Block-API) to have a better idea of the API.

Now let's build our custom block, shall we? ;)

To begin extending the plugin, we will create a custom directory to house all of the files needed by the blocks in our theme. In my Cuvette WordPress theme, the structure looks something like this:

/page-builder
-- page-builder.php
-- /blocks
---- my-team-block.php
-- /css
---- my-custom-css.css

Apparently the real structure are actually more complex than this, with addition of custom CSS, JS and images files but for the sake of simplicity, let's just focus on that simple directory structure first.

In your theme's functions.php file, you would simply reference to the page-builder.php file as such:

require_once('page-builder/page-builder.php');

The page-builder.php file handles the registrations of our custom blocks and CSS files. For now, what you need is just a few lines of code as below:

if(class_exists('AQ_Page_Builder')) {

	define('AQPB_CUSTOM_DIR', get_template_directory() . '/page-builder/');
	define('AQPB_CUSTOM_URI', get_template_directory_uri() . '/page-builder/');

	//include the block files
	require_once(AQPB_CUSTOM_DIR . 'blocks/my-team-block.php');

	//register the blocks
	aq_register_block('My_Team_Block');

}

Since we will be needing some stylings for our Team block, you will also be needing a CSS file to store these values. For this, the plugin included a custom hook called the 'aq-page-builder-view-enqueue'. The hook functions is just like the 'init' hook except that it's only being ran when a custom AQPB's template shortcode is being used on one of your WordPress' page. Technically, you could just include the custom styling in your main style.css file with negligible impact on your theme's load time but in the long run as you're adding more custom blocks and consequently more CSS stylings, you will soon appreciate the fact that all your custom CSS codes are organized into one place and only being called where it is truly needed.

To complete the page-builder.php file above, here's what the final codes look like:

if(class_exists('AQ_Page_Builder')) {

	define('AQPB_CUSTOM_DIR', get_template_directory() . '/admin/page-builder/');
	define('AQPB_CUSTOM_URI', get_template_directory_uri() . '/admin/page-builder/');

	//include the block files
	require_once(AQPB_CUSTOM_DIR . 'blocks/my-team-block.php');

	//register the blocks
	aq_register_block('My_Team_Block');

	//custom block css/js
	add_action('aq-page-builder-view-enqueue', 'my_custom_block_css');
	function my_custom_block_css() {
		wp_register_style( 'my-custom-block-css',  AQPB_CUSTOM_URI . 'css/aqpb-custom-admin.css', array(), time(), 'all');
		wp_enqueue_style('my-custom-block-css');
	}

}

Now let's move on to our my-team-block.php file's content.

Basic block construction

We start by extending the main AQ_Block class, and to make sure a child theme is able to override this, we will also make the class pluggable using class_exists() http://php.net/manual/en/function.class-exists.php

<?php
/** My Custom Team Block **/

if(!class_exists('My_Team_Block')) {
	class My_Team_Block extends AQ_Block {

	}
}

The next thing to do is to define some variables and constructing the sub-class. For this, we will define the basic options for the block, then using them to instanstiate the sub-class.

function __construct() {

	$block_options = array (
		'name' => 'Team Member',
		'size' => 'span6',
	);
	
	parent::__construct('aq_team_block', $block_options);

}

Note that the $block_options is completely optional, but you should at least define the name of the block or otherwise it will confuse the users.

Block Form Fields

Our block needed some custom fields for the users to fill in the data of the Team member, and for this we use the form() method to build the form fields. We start defining the default key/values of each field in the block, as such:

function form($instance) {
	
	// default key/values array
	$defaults = array(
		'title' 	=> '', // the name of the member
		'position'	=> '', // job position
		'avatar'	=> '', // profile picture
		'bio'		=> '', // a little info about the member
		'url'		=> '', // website URL
		'twitter' 	=> '', // twitter URL
		'facebook'	=> '', // facebook URL
		'linkedin'	=> '', // linkedin URL
		'google'	=> '', // google+ URL
	);

	// set default values (if not yet defined)
	$instance = wp_parse_args($instance, $defaults);

	// import each array key as variable with defined values
	extract($instance);

}

Feel free to add more custom social link fields as you feel necessary :)

The final codes for the actual form fields are as below:

<p class="description half">
	<label for="<?php echo $this->get_field_id('title') ?>">
		Member Name (required)<br/>
		<?php echo aq_field_input('title', $block_id, $title) ?>
	</label>
</p>

<p class="description half last">
	<label for="<?php echo $this->get_field_id('title') ?>">
		Member Name (required)<br/>
		<?php echo aq_field_input('title', $block_id, $title) ?>
	</label>
</p>

<div class="description">
	<label for="<?php echo $this->get_field_id('avatar') ?>">
		Upload an image<br/>
		<?php echo aq_field_upload('avatar', $block_id, $avatar) ?>
	</label>
	<?php if($avatar) { ?>
	<div class="screenshot">
		<img src="<?php echo $avatar ?>" />
	</div>
	<?php } ?>
</div>

<p class="description">
	<label for="<?php echo $this->get_field_id('bio') ?>">
		Member info
		<?php echo aq_field_textarea('bio', $block_id, $bio, $size = 'full') ?>
	</label>
</p>

<p class="description half">
	<label for="<?php echo $this->get_field_id('twitter') ?>">
		Title<br/>
		<?php echo aq_field_input('twitter', $block_id, $twitter) ?>
	</label>
</p>

<p class="description half last">
	<label for="<?php echo $this->get_field_id('facebook') ?>">
		Title<br/>
		<?php echo aq_field_input('facebook', $block_id, $facebook) ?>
	</label>
</p>

<p class="description half">
	<label for="<?php echo $this->get_field_id('linkedin') ?>">
		Title<br/>
		<?php echo aq_field_input('linkedin', $block_id, $linkedin) ?>
	</label>
</p>

<p class="description half last">
	<label for="<?php echo $this->get_field_id('google') ?>">
		Title<br/>
		<?php echo aq_field_input('google', $block_id, $google) ?>
	</label>
</p>

There are few important things that's going on in there, and I will attempt to explain them as detailed as possible in the following texts.

i. The "description", "half" and "last" classes

This "description" class is basically a wrapper for each form fields to prevent overlapping. The "half" class, as you might have guessed, will limit the width of the wrapper to 50% of the total block width and the "last" class will simply remove the right margin of the wrapper. In addition to the "half" class, we also have the "third" and "fourth" which I'm sure you can figure what they're for by now.

ii. $this->get_field_id($field_id)

This will dynamically return the correct field ID of the form field, which is useful for myriads of applications and in our example, the label. We also have the $this->get_field_name($field_id) which you can use for your own custom fields. Both of these useful class method are defined in the AQ_Block class.

iii. aq_field_$field_type($arg1, $arg2 ...) function

These neat functions are called the "Form fields helper" and they are your best friends when it comes to constructing your form fields. They provide a simple way to build the forms without even touching the complex HTML codes behind it. There are plenty of supported form fields and you can find the list and examples of how to use each of them in our Wiki - Form Fields Helper

Block Output

So far we have covered the basic construction of our Team Block and now it's time to move on with the front end output of our block. To do this, we will wrapping output in the block() function.

Similar to the form() function, we start off by defining all the default fields of the block and extracting them to be used in our HTML codes. It looks as below:

function block() {

	// default key/values array
	$defaults = array(
		'title' 	=> '', // the name of the member
		'position'	=> '', // job position
		'avatar'	=> '', // profile picture
		'bio'		=> '', // a little info about the member
		'url'		=> '', // website URL
		'twitter' 	=> '', // twitter URL
		'facebook'	=> '', // facebook URL
		'linkedin'	=> '', // linkedin URL
		'google'	=> '', // google+ URL
	);

	// set default values (if not yet defined)
	$instance = wp_parse_args($instance, $defaults);

	// import each array key as variable with defined values
	extract($instance);

}

If you have any comments please post on the issues page

Clone this wiki locally