-1

Dynamic HTML not displaying at respective place I have a created shortcode in function.php and my code is,

function Post_home(){
$data='<div class="cp-seeWrapper"><div class="container"><div class="row"><div class="col-xl-8 col-lg-8 col-md-8 col-sm-12 col-xs-12">';

  //some logic here

  $data.='</div>';
  $data.='<div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 col-xs-12"><div class="cp-social">';
            if (is_active_sidebar('footer-social')) :
                 dynamic_sidebar('footer-social');
                endif;
  $data.='</div><div class="cp-newsletter">';
           if (is_active_sidebar('cp_newsletter')) :
                 dynamic_sidebar('cp_newsletter');
                endif;
  $data.='</div></div></div></div></div>';
 return $data;    
}
add_shortcode( 'home_post', 'Post_home' );

Now just notice here, Whatever I am adding the logic part that output is displaying before the parent div. I mean my parent div is cp-seeWrapper and output is displaying before it.

I added footer-social and newsletter logic and both are displaying above parent div.

Would you help me out?

My output is

//I am getting my output here
    <div class="cp-seeWrapper">
      <div class="container">
        <div class="row">
          <div class="col-xl-8 col-lg-8 col-md-8 col-sm-12 col-xs-12">
          </div>
          <div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 col-xs-12">
            <div class="cp-social"></div>
            <div class="cp-newsletter"></div>
          </div>
        </div>
      </div>
    </div>

I have created widget on function.php

function cp_newsletters() {
    register_sidebar( array(
        'name'          => 'Newsletter',
        'id'            => 'cp_newsletter',
        'before_widget' => '<div class="chw-newsletter">',
        'after_widget'  => '</div>',
        'before_title'  => '<h2 class="chw-newsletter_title">',
        'after_title'   => '</h2>',
    ) );

}
add_action( 'widgets_init', 'cp_newsletters' );
4
  • If your shortcode function needs to echo the output, then you should use output buffering. And I said so because dynamic_sidebar() echoes the sidebar's widgets.
    – Sally CJ
    Commented Nov 1, 2019 at 14:29
  • @SallyCJ, So I have to add ob_start();? Commented Nov 1, 2019 at 14:32
  • @SallyCJ, I have created a widget in function.php (Code added in the question.) and then I am calling on another function. Commented Nov 1, 2019 at 14:37
  • Yes, call ob_start() as in my answer..
    – Sally CJ
    Commented Nov 1, 2019 at 14:46

1 Answer 1

2

You're getting the output there because dynamic_sidebar() displays/echoes the output (widgets in the specific sidebar), so the output is echoed right when the shortcode function is called, which is before the $data is actually echoed.

And you can fix that using output buffering:

  1. Either append the output to $data:

    $data.='</div>';
    $data.='<div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 col-xs-12"><div class="cp-social">';
    if (is_active_sidebar('footer-social')) :
        ob_start();
        dynamic_sidebar('footer-social'); // echoes the widgets
        $data .= ob_get_clean();          // append the output
    endif;
    $data.='</div><div class="cp-newsletter">';
    if (is_active_sidebar('cp_newsletter')) :
        ob_start();
        dynamic_sidebar('cp_newsletter'); // echoes the widgets
        $data .= ob_get_clean();          // append the output
    endif;
    $data.='</div></div></div></div></div>';
    

    You can turn on/off output buffering at anytime, and you should do the same as above with the cp_newsletter sidebar.

    Update: Not sure why this option is not working for you, but maybe the updated code can help?

  2. Or (maybe easier), echo everything in your function:

    function Post_home() {
        ob_start();
        ?>
            <div class="cp-seeWrapper">
              <div class="container">
                <div class="row">
                  <div class="col-xl-8 col-lg-8 col-md-8 col-sm-12 col-xs-12">
                  </div>
                  <div class="col-xl-4 col-lg-4 col-md-4 col-sm-12 col-xs-12">
                    <div class="cp-social">
                      <?php if ( is_active_sidebar( 'social-footer' ) ) dynamic_sidebar( 'social-footer' ); ?>
                    </div>
                    <div class="cp-newsletter">
                      <?php if ( is_active_sidebar( 'cp_newsletter' ) ) dynamic_sidebar( 'cp_newsletter' ); ?>
                    </div>
                  </div>
                </div>
              </div>
            </div>
        <?php
        return ob_get_clean();
    }
    

UPDATE

For option #1, you might want to consider caching either the widgets (i.e. the output returned by the ob_get_clean() call) or your shortcode output (i.e. the entire content of the $data). I suggested that for performance reasons where the shortcode could be called twice or more on the same page.

Additionally, if you're going to use option #2 (echo everything), then you might want to consider creating a template and do something like:

function Post_home() {
    ob_start();
    locate_template( 'my-template.php', true );
    return ob_get_clean();
}
5
  • Which one is the best answer? Commented Nov 1, 2019 at 18:56
  • That would depend on your code, but whichever is easier for you, just go with it. And if you need further assistance in deciding the best, SO is a better place for that. So if the answer helps, you can either accept it or upvote it..
    – Sally CJ
    Commented Nov 2, 2019 at 0:06
  • Yes, I tried first one and it's working for me. Thanks for the help. Upvote from my side. Commented Nov 2, 2019 at 2:58
  • Thanks, and perhaps the revised answer can help (with that first option not working)..
    – Sally CJ
    Commented Nov 2, 2019 at 14:26
  • 1
    thanks for the help again. Commented Nov 2, 2019 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.