Container Blocks (Nesting) ​
Container blocks are blocks that accept child blocks, enabling deep nesting and sophisticated page layouts. This feature transforms the theme editor into a true page builder.
What are Container Blocks? ​
Container blocks are regular blocks with one key difference: they can accept other blocks as children. This enables:
- Multi-column layouts with different content in each column
- Tabbed content with blocks inside each tab
- Accordions with rich content in each panel
- Nested structures up to 8 levels deep
Creating a Container Block ​
To create a container block, define the $accepts property:
<?php
namespace Themes\YourTheme\Blocks;
use BagistoPlus\Visual\Block\SimpleBlock;
use BagistoPlus\Visual\Settings\Select;
class Columns extends SimpleBlock
{
protected static string $view = 'shop::blocks.columns';
/**
* Define which blocks can be nested
*/
protected static array $accepts = ['@awesome-theme/*']; // Accept all theme blocks
public static function settings(): array
{
return [
Select::make('column_count', 'Number of Columns')
->options([
'2' => '2 Columns',
'3' => '3 Columns',
'4' => '4 Columns',
])
->default('3'),
];
}
}Rendering Child Blocks ​
In the container block's view, use the @children directive to render child blocks:
{{-- resources/views/blocks/columns.blade.php --}}
<div class="columns columns--{{ $block->settings->column_count }}">
@children
</div>Sharing Data with Child Blocks ​
Container blocks can share data with their children using the share() method. Data returned from share() is automatically passed down the entire nested structure, making it available to all descendant blocks.
How It Works ​
The share() method returns an array of data that becomes available in:
- Child block classes: Access via
$this->context('key', 'default') - Child block views: Available as variables (e.g.,
$product,$category) - Child block presets: Use dynamic sources with
@keysyntax (e.g.,'@product.name') - Deeply nested blocks: Automatically cascades to grandchildren and beyond
Example 1: Product Card Sharing Product Data ​
The ProductCard container shares the product object so child blocks don't need their own product settings:
class ProductCard extends SimpleBlock
{
protected static string $view = 'shop::blocks.product-card';
protected static array $accepts = [
'@awesome-theme/product-image',
'@awesome-theme/product-title',
'@awesome-theme/product-price',
];
public static function settings(): array
{
return [
Product::make('product', 'Product'),
];
}
public function share(): array
{
return [
'product' => $this->block->settings->product ?? $this->context('product')
];
}
}Now child blocks can access the shared product data:
In child block classes:
class ProductImage extends SimpleBlock
{
protected function getViewData(): array
{
$product = $this->context('product');
return [
'imageUrl' => $product?->base_image->url,
];
}
}In child block views:
{{-- In product-image.blade.php view --}}
@if($product)
<img src="{{ $product->base_image->url }}" alt="{{ $product->name }}">
@endifIn child block presets using dynamic sources:
PresetBlock::make('@awesome-theme/product-image')
->settings([
'src' => '@product.base_image.url',
'alt' => '@product.name',
]),
PresetBlock::make('@awesome-theme/product-title')
->settings([
'text' => '@product.name',
'url' => '@product.url',
]),The @ syntax automatically resolves to the shared data at runtime.
Example 2: Accordion Sharing Icon Type ​
The Accordion container shares its icon setting with all accordion items:
class Accordion extends SimpleBlock
{
protected static string $view = 'shop::blocks.accordion';
protected static array $accepts = ['@awesome-theme/accordion-item'];
public static function settings(): array
{
return [
Select::make('icon', 'Icon Type')
->options([
'caret' => 'Caret',
'plus' => 'Plus/Minus',
])
->default('caret'),
];
}
public function share(): array
{
return [
'accordionIconType' => $this->block->settings->icon ?? 'caret',
];
}
}All accordion items automatically receive the icon type:
{{-- In accordion-item.blade.php view --}}
<button class="accordion-trigger">
<span>{{ $block->settings->title }}</span>
<span class="icon">
@if ($accordionIconType === 'caret')
<x-icon name="chevron-down" />
@else
<x-icon name="plus" />
@endif
</span>
</button>Next Steps ​
- Block Attributes: Configure accepted blocks and limits
- Section Attributes: Configure which blocks sections accept