What is the proper code to embed a block (with all it's proper classes and markup) into a template?

And, since you most likely need the module name and block_id for embedding, how do you most easily discover those?

Most helpful answers

I'm surprised you havent noticed the two answers above your comment.

This should work:

$block = module_invoke('module_name', 'block_view', 'block_delta');
print render($block['content']);

 

Comments

Why would you want to do that rather than have it in a layout?

I'm trying to keep the question general so it applies to anyone wondering how to do this, but there could be lots of cases where you want to put a block into a specific place that's not part of a layout region.

It could be embedded in a node template, embedded in a particular portion of a header that's not a region, heck...embedding a block within another block.  Basically theres many cases where you'd want to do this outside of a layout/region...so I'm wondering what the recommended embed code is.  Thanks!

Good point. 

There are two ways of coding a block in Backdrop: the usual hook_block_info/configure/save/view, and the plugin type blocks which extend Block Class. 

With the normal blocks, I imagine the D7 method should still work. Not sure how the plugn type blocks could be embedded though.

I would create an empty layout region for this block in my custom template and then I would place the block in that region.

I guess I'm surprised no one really has an answer for this...it was an easy thing to do in Drupal, seems like it should be easy here too, but I can't figure it out (yet)!

I'm surprised you havent noticed the two answers above your comment.

This should work:

$block = module_invoke('module_name', 'block_view', 'block_delta');
print render($block['content']);

 

This helped me figure out how to embed the search block (and pass along some arguments):

$searchblock = module_invoke('search', 'block_view', 'search_block', array( 'search' => array('placeholder' => 'Search', 'button_text' => '')));
print render($searchblock['content']);

thanks, I tried this previously and it wouldn't render.  I noticed the 2 comments above, but didn't really see how they could be applied (I didn't want to create a region and I wasn't sure how the other translated into code).

I guess I'll try this again, but it leads to my other original question on how to discover the module/block_id for the block (in Drupal you could edit the block and see them in the URL, but you can't do that in backdrop). 

I've tried various combinations, but from what I could tell the module should be 'menu' and the block_id for the primary links should be (main-menu or main_menu).

Understood. For main menu the block is main_menu, the module is system. 

If you inspect the code, the class block-system-main-menu gives a clue, but youre right, its not obvious.

Hmm...for the record this doesn't seem to work.  I get nothing rendered in my header.tpl.php when I put in:

<?php
$block = module_invoke('system', 'block_view', 'main_menu');
print render($block['content']);
?>

EDIT: It should be "main-menu" not "main_menu".

But now it looks like I'm back to square one...I have the main nav rendered that way, but I have no way to display them as a dropdown menu...it's just a standard hierarchy of items.

And as an additional piece of info for future Googlers...I wasn't able to figure out how to render a region within the header.tpl.php.  Regions are in Layouts, header.tpl.php is in the theme.  I tried adding a region declaration to my theme, then putting the region in my header.tpl file, but that didn't work. 

So...I'd be open to adding a region instead of custom printing the nav, but I'm not sure if it's possible (since I have to render it in the header.tpl file, not in a layout)

Have you tried adding the region to the layout as well?

How custom are you trying to make this menu? Are you just trying to embed a block that is configured in the same way it is configured on a certain layout (in which case adding the region to the layout and adding/configuring the block there seems the best bet), or something more elemental, like using menu_tree_all_data and doing a completely custom menu build from scratch?

Hehe, yeah, you'd think I was trying to do something crazy.  I'm not.  I'm simply trying to embed the primary links menu into the header.tpl template...but WITH the option to make it a dropdown menu.  As far as I can tell, the only way to get the option (to make it a dropdown) is by adding it via a Layout (and it gives you the option when configuring the block).

(it just occurred to me that this dropdown config might be just for the bootstrap_lite theme? not sure if that' core or not...but the question still stands:  how to add a block in a custom place with any block settings configured)

Totally spitballing (and @docwilmot would know more about this than I) but if it's not easy to do this via core functions, perhaps the copy_blocks module contains some code that could be useful here? (e.g. a function that allows you to copy X block from Y layout and Z region and return it with appropriate configuration when this function is called). If it can't be done in the module currently, perhaps even a helper function could be added to this module that took inputs such as block name, layout and region.

Although it's still not completely clear to me why this won't work for you by simply adding the region in the layout, and adding the block to that region, to be honest! I know I don't have the entire situation in front of me.

For the 'why not a region' question, it is, indeed, one of those things you'd need to see.  Basically the header.tpl.php is where a lot of stuff happens in this layout (not just the nav), so all that 'stuff that happens' needs to stay in that template file.  But the nav needs to be one piece within all that.

I wasn't able to put a region inside the header.tpl template (that would end up being a nav region inside a header region, basically)...it just doesn't seem like a region will work where it needs to, from what I can see.

Well, sorry to repeat, but again, best bet, instead of creating a tpl file or whatever, create a layout, and stick the block in there. 

But in this case, I suspect the smartmenus library isnt being loaded. So maybe in your template.php do a backdrop_add_library('system', 'smartmenus').

Yeah, I'm trying not to get too 'in the weeds' with specifics related to my build, but creating a layout with a region isn't really an option.  Bootstrap does a crazy thing with a header region which just doesn't really make it feasible to do this as a region...if it was easy, that certainly would have been my solution.

I hate to do it, but I may have to 'tear down' this whole thing and come up with a different way to build it.  I just didn't anticipate embedding the nav being a bigger issue like this.

I'll try the library solution, but I have a feeling that's not really the issue...because the menu defaults to the 'non-dropdown version', and there's nothing that I'm doing which would switch it's configuration into the 'dropdown version'.  (again, trying not to get too specific because that generally just confuses the issue, thats why I started with the simple "how do I embed a block" question...)

Understood.

But I'd doubt the library was being loaded though, with just invoking the block view hook. The code that loads it does this:

      if ($config['style'] === 'dropdown') {
        $data['content']['#attached']['library'][] = array('system', 'smartmenus');
      }

Style would be set if youre just invoking directly. (This is a difference from D7). So you'd likely need to load the library. Or maybe try 

$block = module_invoke('system', 'block_view', 'main_menu', array('style' => 'dropdown'));
 

 

If the block is from a View, this works in your block template:

<div class="<?php print implode(' ', $classes); ?>"<?php print backdrop_attributes($attributes); ?>>

    <?php print render($content); 
    print render(views_embed_view('viewname'));
    ?>
  
</div>

Where viewname is the machine name of the view; case-sensitive.

If the block is from a Web form, this works in your page node template:

<?php

$block = module_invoke('webform', 'block_view', 'webform:client-block-nid');

print render($block['content']);

?>

Replace nid with the numerical id of your webform node.

And make sure that the webform advanced settings allow block.