How to create a new WPBakery (Visual Composer) component

,

If you use WPBakery in the past and want to build your own custom component, look no more. In this blog post, we will build our own WPBakery component that allows us to use our own semantic HTML and design it the way we want it. If you wonder why we don’t install a plugin likeMega Addons For WPBakery Page Builder and customize it, it is because page speed is important. Every plugin that we install comes with extra CSS and JS files. Those can add up and really bite into your performance budget. On top of that, we want to have tight control over the design of our components.

Where do I add the code?

As I wrote in “How to remove unused components from WPBakery (Visual Composer)” we like to create a small plugin “sodawebmedia-wpbakery” where we add all of our custom WPBakery modules. If you choose not to have a small plugin and prefer to have the code in the theme folder, I recommend creating a separate file for your modules. While you could add all the code in functions.php, it can get messy and confusing very quickly. Instead, create a folder, something like vc-components and inside create a file that reflects the component you are about to custom code. In our case, we can have vc-soda-blockquote.php. Now, in function.php we can reference our file.

// Require new custom Element
    require_once( get_template_directory().'/vc-components/vc-soda-blockquote.php' ); 

Creating the new WPBakery component

Before we show you the code, we want to say that there are many ways to build it. This is an example of how we build a new WPBakery component if it will be placed in a plugin folder instead of the theme folder. We start by creating a new class VcSodaBlockquote, extend WPBakeryShortCode, and add the basic structure of the component

if ( ! class_exists( 'VcSodaBlockquote' ) ) {

    class VcSodaBlockquote extends WPBakeryShortCode {

        //Initialize Component
        function __construct() {
            add_action( 'init', array( $this, 'create_shortcode' ), 999 );            
            add_shortcode( 'vc_soda_blockquote', array( $this, 'render_shortcode' ) );

        }        

        //Map Component
        public function create_shortcode() {
        
            //Code in the next steps

        }

        //Render Component
        public function render_shortcode( $atts, $content, $tag ) {
            //Code in the next steps
        }

    }

    new VcSodaBlockquote();

}

Create Shortcode

To create a shortcode, we will use vc_map a function provided by WPBakery that allows us to create new fields inside our component. If you want to learn what other fields you can use, check out WPBakery Page Builder (formerly Visual Composer) – vc_map() field examples

In our example, we will create 5 fields: a content field, 3 text fields, and a link button.

public function create_shortcode() {
    // Stop all if VC is not enabled
    if ( !defined( 'WPB_VC_VERSION' ) ) {
        return;
    }        

    // Map blockquote with vc_map()
    vc_map( array(
        'name'          => __('Blockquote ', 'sodawebmedia'),
        'base'          => 'vc_soda_blockquote',
        'description'  	=> __( '', 'sodawebmedia' ),
        'category'      => __( 'SodaWebMedia Modules', 'sodawebmedia'),                
        'params' => array(

            array(
                "type" => "textarea_html",
                "holder" => "div",
                "class" => "",                     
                "heading" => __( "Blockquote Content", 'sodawebmedia' ),
                "param_name" => "content", // Important: Only one textarea_html param per content element allowed and it should have "content" as a "param_name"
                "value" => __( "<p>I am test text block. Click edit button to change this text.</p>", 'sodawebmedia' ),
                "description" => __( "Enter content.", 'sodawebmedia' )
            ),    

            array(
                'type'          => 'textfield',
                'heading'       => __( 'Author Quote', 'sodawebmedia' ),
                'param_name'    => 'quote_author',
                'value'         => __( '', 'sodawebmedia' ),
                'description'   => __( 'Add Author Quote.', 'sodawebmedia' ),
            ),


            array(
                "type" => "vc_link",
                "class" => "",
                "heading" => __( "Blockquote Cite", 'sodawebmedia' ),
                "param_name" => "blockquote_cite",
                "description" => __( "Add Citiation Link and Source Name", 'sodawebmedia' ),                                                
            ),    

            array(
                'type'          => 'textfield',
                'heading'       => __( 'Element ID', 'sodawebmedia' ),
                'param_name'    => 'element_id',
                'value'             => __( '', 'sodawebmedia' ),
                'description'   => __( 'Enter element ID (Note: make sure it is unique and valid).', 'sodawebmedia' ),
                'group'         => __( 'Extra', 'sodawebmedia'),
            ),

            array(
                'type'          => 'textfield',
                'heading'       => __( 'Extra class name', 'sodawebmedia' ),
                'param_name'    => 'extra_class',
                'value'             => __( '', 'sodawebmedia' ),
                'description'   => __( 'Style particular content element differently - add a class name and refer to it in custom CSS.', 'sodawebmedia' ),
                'group'         => __( 'Extra', 'sodawebmedia'),
            ),               
        ),
    ));             

}

Render Shortcode

We are finally ready to work on the front end layout. render_shortcode will allow us to extract the values and save them in variables for later use. Before we display the content, it is important to escape our variable for security reasons. In case we have a database breach, we want to ensure that everything that will be output on the website is output in a safe mode. If can learn more about how to secure your output on WordPress Developer Resources.

public function render_shortcode( $atts, $content, $tag ) {
    $atts = (shortcode_atts(array(
        'blockquote_cite'   => '',
        'quote_author'      => '',
        'extra_class'       => '',
        'element_id'        => ''
    ), $atts));


    //Content 
    $content            = wpb_js_remove_wpautop($content, true);
    $quote_author       = esc_html($atts['quote_author']);

    //Cite Link
    $blockquote_source  = vc_build_link( $atts['blockquote_cite'] );
    $blockquote_title   = esc_html($blockquote_source["title"]);
    $blockquote_url     = esc_url( $blockquote_source['url'] );

    //Class and Id
    $extra_class        = esc_attr($atts['extra_class']);
    $element_id         = esc_attr($atts['element_id']);
    


    $output = '';
    $output .= '<div class="blockquote ' . $extra_class . '" id="' . $element_id . '" >';
    $output .= '<blockquote cite="' . $blockquote_url . '">';
    $output .= $content;
    $output .= '<footer>' . $quote_author . ' - <cite><a href="' . $blockquote_url . '">' . $blockquote_title . '</a></cite></footer>';
    $output .= '</blockquote>';
    $output .= '</div>';

    return $output;                  

}

Results and Complete Code

In our WordPress dashboard, we should have our new component.

WPBakery Component Showing in WordPress interface

WPBakery Component Showing in WordPress interface. It displays the fields it can be filled to display the Blockquote compoennt

For full code, you can download our small plugin from our GitHub repository. If you want to add it to your plugin, copy the full code.

class VcSodaBlockquote extends WPBakeryShortCode {

    function __construct() {
        add_action( 'init', array( $this, 'create_shortcode' ), 999 );            
        add_shortcode( 'vc_soda_blockquote', array( $this, 'render_shortcode' ) );

    }        

    public function create_shortcode() {
        // Stop all if VC is not enabled
        if ( !defined( 'WPB_VC_VERSION' ) ) {
            return;
        }        

        // Map blockquote with vc_map()
        vc_map( array(
            'name'          => __('Blockquote', 'sodawebmedia'),
            'base'          => 'vc_soda_blockquote',
            'description'  	=> __( '', 'sodawebmedia' ),
            'category'      => __( 'SodaWebMedia Modules', 'sodawebmedia'),                
            'params' => array(

                array(
                    "type" => "textarea_html",
                    "holder" => "div",
                    "class" => "",                     
                    "heading" => __( "Blockquote Content", 'sodawebmedia' ),
                    "param_name" => "content", // Important: Only one textarea_html param per content element allowed and it should have "content" as a "param_name"
                    "value" => __( "<p>I am test text block. Click edit button to change this text.</p>", 'sodawebmedia' ),
                    "description" => __( "Enter content.", 'sodawebmedia' )
                ),    

                array(
                    'type'          => 'textfield',
                    'holder'        => 'div',
                    'heading'       => __( 'Author Quote', 'sodawebmedia' ),
                    'param_name'    => 'quote_author',
                    'value'         => __( '', 'sodawebmedia' ),
                    'description'   => __( 'Add Author Quote.', 'sodawebmedia' ),
                ),


                array(
                    "type" => "vc_link",
                    "class" => "",
                    "heading" => __( "Blockquote Cite", 'sodawebmedia' ),
                    "param_name" => "blockquote_cite",
                    "description" => __( "Add Citiation Link and Source Name", 'sodawebmedia' ),                                                
                ),    

                array(
                    'type'          => 'textfield',
                    'heading'       => __( 'Element ID', 'sodawebmedia' ),
                    'param_name'    => 'element_id',
                    'value'             => __( '', 'sodawebmedia' ),
                    'description'   => __( 'Enter element ID (Note: make sure it is unique and valid).', 'sodawebmedia' ),
                    'group'         => __( 'Extra', 'sodawebmedia'),
                ),

                array(
                    'type'          => 'textfield',
                    'heading'       => __( 'Extra class name', 'sodawebmedia' ),
                    'param_name'    => 'extra_class',
                    'value'             => __( '', 'sodawebmedia' ),
                    'description'   => __( 'Style particular content element differently - add a class name and refer to it in custom CSS.', 'sodawebmedia' ),
                    'group'         => __( 'Extra', 'sodawebmedia'),
                ),               
            ),
        ));             

    }

    public function render_shortcode( $atts, $content, $tag ) {
        $atts = (shortcode_atts(array(
            'blockquote_cite'   => '',
            'quote_author'      => '',
            'extra_class'       => '',
            'element_id'        => ''
        ), $atts));


        //Content 
        $content            = wpb_js_remove_wpautop($content, true);
        $quote_author       = esc_html($atts['quote_author']);

        //Cite Link
        $blockquote_source  = vc_build_link( $atts['blockquote_cite'] );
        $blockquote_title   = esc_html($blockquote_source["title"]);
        $blockquote_url     = esc_url( $blockquote_source['url'] );

        //Class and Id
        $extra_class        = esc_attr($atts['extra_class']);
        $element_id         = esc_attr($atts['element_id']);
        


        $output = '';
        $output .= '<div class="blockquote ' . $extra_class . '" id="' . $element_id . '" >';
        $output .= '<blockquote cite="' . $blockquote_url . '">';
        $output .= $content;
        $output .= '<footer>' . $quote_author . ' - <cite><a href="' . $blockquote_url . '">' . $blockquote_title . '</a></cite></footer>';
        $output .= '</blockquote>';
        $output .= '</div>';

        return $output;                  

    }

}

new VcSodaBlockquote();

What components do you plan to build in WPBakery?

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments