I have a nested element called Hero Slider
. Hero slider
is the container and it can only contain a Slider item
.
However, my shortcode is being shown in the WPBakery backend maybe suggesting a syntax error, but I cannot see anything that is causing it to appear this way:
The block doesn't even appear when adding a new element.
Here's my custom element:
<?php
if (!defined('ABSPATH')) die('-1');
class vcHeroSlider extends WPBakeryShortCode {
// 1. Define constants at compile time (used in mapping)
const slug = 'tp_hero_slider';
const base = 'tp_hero_slider';
// 2. Integrate with hooks
function __construct() {
// For the parent wrapper
add_action( 'vc_before_init', array( $this, 'tp_heroSlider_mapping' ) );
add_shortcode( 'tp_hero_slider', array( $this, 'tp_heroSlider_html' ));
// For child / nested
add_action( 'vc_before_init', array( $this, 'tp_heroSlider_content_mapping' ) );
add_shortcode( 'tp_hero_slider_content', array( $this, 'tp_heroSlider_content_html' ));
}
// 3. Map for parent element
public function tp_heroSlider_mapping() {
vc_map(
array(
'icon' => get_template_directory_uri().'/assets/src/images/html.svg',
'name' => __( 'Hero Slider' , "text-domain" ),
'base' => 'tp_hero_slider',
'description' => __( 'Add slick slider to your page.', "text-domain" ),
'as_parent' => array('only' => 'tp_hero_slider_content'), // set as parent of the content map/html
'content_element' => true,
'show_settings_on_create' => false,
"js_view" => 'VcColumnView',
"category" => __('Hero', "text-domain" ),
'params' => array(
array(
"type" => "textfield",
"heading" => __( "Extra Class Name", "text-domain" ),
"param_name" => "el_class",
"description" => __( "Extra class to be customized via CSS", "text-domain" )
),
array(
'type' => 'css_editor',
'heading' => __( 'Custom Design Options', "text-domain" ),
'param_name' => 'css',
'group' => __( 'Design options', "text-domain" ),
),
),
)
);
}
// 4. Map for child element
public function tp_heroSlider_content_mapping() {
vc_map(
array(
'icon' => get_template_directory_uri().'/assets/src/images/html.svg',
'name' => __('Slider Item', "text-domain" ),
'base' => 'tp_hero_slider_content',
'description' => __( 'Add slide to hero.', "text-domain" ),
"category" => __('Content', 'text-domain'),
'content_element' => true,
'as_child' => array('only' => 'tp_hero_slider'),
'params' => array(
array(
'type' => 'textfield',
'heading' => __( 'Title', 'text-domain'),
'param_name' => 'title',
'value' => esc_html__( '', 'text-domain'),
'admin_label' => true,
'weight' => 0,
'group' => __( 'Content', 'my-text-domain' ),
),
array(
'type' => 'textarea',
'class' => '',
'heading' => __( 'Standfirst', 'text-domain'),
'param_name' => 'standfirst',
'value' => esc_html__( '', 'text-domain'),
'admin_label' => false,
'weight' => 0,
'group' => __( 'Content', 'my-text-domain' ),
)
),
)
);
}
// 5. Mapping markup of parent
public function tp_heroSlider_html( $atts, $content = null) {
$output = '';
$el_class = '';
extract(
shortcode_atts(
array(
'el_class' => '',
), $atts
)
);
static $i = 0;
$output = '<div id="slickslider-'.$i++.'" class="Slick-Slider heroSlider">'. do_shortcode($content) .'</div>';
return $output;
}
// 6. Mapping markup of child
public function tp_heroSlider_content_html( $atts, $content = null ) {
$output = '';
extract(
shortcode_atts(
array(
'title' => '',
'standfirst' => '',
), $atts
)
);
$background_img = wp_get_attachment_image_src(intval($background_img), 'full');
$background_img = $background_img[0];
$output .= '
<!-- Slide -->
<div class="heroSlider__slide">
<div class="overlay"></div>
';
$output .= '
<div class="container">
<div class="row justify-content-center justify-content-lg-start">
<div class="col-10 col-md-6 d-flex flex-column text-center text-lg-left content">';
if (!empty($title)) {
$output .= '<h1>' . $title . '</h1>';
}
if (!empty($standfirst)) {
$output .= '<p class="standfist">' . $standfirst . '</p>';
}
$output .= '
</div>
</div>
</div>
</div>
<!-- Slide -->
';
return $output;
}
}
// 7. Add the container functionality (so you can choose a slider element within the hero_slider element
if(class_exists('WPBakeryShortCodesContainer')){
class WPBakeryShortCode_tp_hero_slider extends WPBakeryShortCodesContainer {}
}
if(class_exists('WPBakeryShortCode')){
class WPBakeryShortCode_tp_hero_slider_content extends WPBakeryShortCode {}
}
new vcHeroSlider(); ?>
I have a nested element called Hero Slider
. Hero slider
is the container and it can only contain a Slider item
.
However, my shortcode is being shown in the WPBakery backend maybe suggesting a syntax error, but I cannot see anything that is causing it to appear this way:
The block doesn't even appear when adding a new element.
Here's my custom element:
<?php
if (!defined('ABSPATH')) die('-1');
class vcHeroSlider extends WPBakeryShortCode {
// 1. Define constants at compile time (used in mapping)
const slug = 'tp_hero_slider';
const base = 'tp_hero_slider';
// 2. Integrate with hooks
function __construct() {
// For the parent wrapper
add_action( 'vc_before_init', array( $this, 'tp_heroSlider_mapping' ) );
add_shortcode( 'tp_hero_slider', array( $this, 'tp_heroSlider_html' ));
// For child / nested
add_action( 'vc_before_init', array( $this, 'tp_heroSlider_content_mapping' ) );
add_shortcode( 'tp_hero_slider_content', array( $this, 'tp_heroSlider_content_html' ));
}
// 3. Map for parent element
public function tp_heroSlider_mapping() {
vc_map(
array(
'icon' => get_template_directory_uri().'/assets/src/images/html.svg',
'name' => __( 'Hero Slider' , "text-domain" ),
'base' => 'tp_hero_slider',
'description' => __( 'Add slick slider to your page.', "text-domain" ),
'as_parent' => array('only' => 'tp_hero_slider_content'), // set as parent of the content map/html
'content_element' => true,
'show_settings_on_create' => false,
"js_view" => 'VcColumnView',
"category" => __('Hero', "text-domain" ),
'params' => array(
array(
"type" => "textfield",
"heading" => __( "Extra Class Name", "text-domain" ),
"param_name" => "el_class",
"description" => __( "Extra class to be customized via CSS", "text-domain" )
),
array(
'type' => 'css_editor',
'heading' => __( 'Custom Design Options', "text-domain" ),
'param_name' => 'css',
'group' => __( 'Design options', "text-domain" ),
),
),
)
);
}
// 4. Map for child element
public function tp_heroSlider_content_mapping() {
vc_map(
array(
'icon' => get_template_directory_uri().'/assets/src/images/html.svg',
'name' => __('Slider Item', "text-domain" ),
'base' => 'tp_hero_slider_content',
'description' => __( 'Add slide to hero.', "text-domain" ),
"category" => __('Content', 'text-domain'),
'content_element' => true,
'as_child' => array('only' => 'tp_hero_slider'),
'params' => array(
array(
'type' => 'textfield',
'heading' => __( 'Title', 'text-domain'),
'param_name' => 'title',
'value' => esc_html__( '', 'text-domain'),
'admin_label' => true,
'weight' => 0,
'group' => __( 'Content', 'my-text-domain' ),
),
array(
'type' => 'textarea',
'class' => '',
'heading' => __( 'Standfirst', 'text-domain'),
'param_name' => 'standfirst',
'value' => esc_html__( '', 'text-domain'),
'admin_label' => false,
'weight' => 0,
'group' => __( 'Content', 'my-text-domain' ),
)
),
)
);
}
// 5. Mapping markup of parent
public function tp_heroSlider_html( $atts, $content = null) {
$output = '';
$el_class = '';
extract(
shortcode_atts(
array(
'el_class' => '',
), $atts
)
);
static $i = 0;
$output = '<div id="slickslider-'.$i++.'" class="Slick-Slider heroSlider">'. do_shortcode($content) .'</div>';
return $output;
}
// 6. Mapping markup of child
public function tp_heroSlider_content_html( $atts, $content = null ) {
$output = '';
extract(
shortcode_atts(
array(
'title' => '',
'standfirst' => '',
), $atts
)
);
$background_img = wp_get_attachment_image_src(intval($background_img), 'full');
$background_img = $background_img[0];
$output .= '
<!-- Slide -->
<div class="heroSlider__slide">
<div class="overlay"></div>
';
$output .= '
<div class="container">
<div class="row justify-content-center justify-content-lg-start">
<div class="col-10 col-md-6 d-flex flex-column text-center text-lg-left content">';
if (!empty($title)) {
$output .= '<h1>' . $title . '</h1>';
}
if (!empty($standfirst)) {
$output .= '<p class="standfist">' . $standfirst . '</p>';
}
$output .= '
</div>
</div>
</div>
</div>
<!-- Slide -->
';
return $output;
}
}
// 7. Add the container functionality (so you can choose a slider element within the hero_slider element
if(class_exists('WPBakeryShortCodesContainer')){
class WPBakeryShortCode_tp_hero_slider extends WPBakeryShortCodesContainer {}
}
if(class_exists('WPBakeryShortCode')){
class WPBakeryShortCode_tp_hero_slider_content extends WPBakeryShortCode {}
}
new vcHeroSlider(); ?>
since the last time I used WP Bakery, shortcodes were not rendered in the back end (unlike with elementor for example). If it also shows it like this in the front end, then you need to make sure that you selected the 'text' tab and not 'visual' for the text-block you added the shortcode to (on the visual it sometimes escapes the brackets).