-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' );
  • 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 Nov 1 at 14:29
  • @SallyCJ, So I have to add ob_start();? – Naren Verma Nov 1 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. – Naren Verma Nov 1 at 14:37
  • Yes, call ob_start() as in my answer.. – Sally CJ Nov 1 at 14:46
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();
}
  • Which one is the best answer? – Naren Verma Nov 1 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 Nov 2 at 0:06
  • Yes, I tried first one and it's working for me. Thanks for the help. Upvote from my side. – Naren Verma Nov 2 at 2:58
  • Thanks, and perhaps the revised answer can help (with that first option not working).. – Sally CJ Nov 2 at 14:26
  • 1
    thanks for the help again. – Naren Verma Nov 2 at 15:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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