Block Pattern Options Trait
The Trait_Block_Pattern_Options
provides blocks with the ability to reference and render reusable block patterns, allowing content editors to insert predefined content structures while maintaining consistency across the site.
Purpose
This trait is designed to:
- Allow blocks to reference reusable block patterns
- Provide ACF field options for pattern selection
- Enable dynamic pattern rendering within blocks
- Maintain consistency across different content areas
- Simplify content management for editors
How It Works
The trait automatically:
- Scans for available reusable blocks (patterns) in the database
- Generates ACF choice fields with pattern options
- Provides methods to render patterns by slug
- Supports both direct pattern rendering and post-context rendering
- Integrates with WordPress's reusable block system
Usage
Basic Implementation
<?php
use Creode_Blocks\Block;
class My_Block extends Block {
use Trait_Block_Pattern_Options;
// ... rest of block implementation
}
Adding Pattern Selection Fields
Use the get_block_pattern_choices()
method to create ACF fields:
<?php
use Creode_Blocks\Block;
class My_Block extends Block {
use Trait_Block_Pattern_Options;
protected function fields(): array {
return array(
array(
'key' => 'field_my_block_pattern',
'name' => 'pattern',
'label' => 'Content Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
);
}
}
Rendering Patterns in Templates
<?php
$pattern_slug = $this->get_field( 'pattern' );
if ( ! empty( $pattern_slug ) ) {
$this->render_block_pattern( $pattern_slug );
}
?>
Available Methods
get_block_pattern_choices()
Returns all configured block patterns for use in ACF select fields.
Returns: array
- An array of pattern choices with slugs as keys and titles as values
Example:
$choices = $this->get_block_pattern_choices();
// Returns: array(
// '' => 'None',
// 'hero-section' => 'Hero Section',
// 'feature-grid' => 'Feature Grid',
// 'testimonial' => 'Testimonial',
// )
render_block_pattern( string $block_pattern_slug )
Renders a block pattern by slug.
Parameters:
$block_pattern_slug
(string) - The slug of the pattern to render
Returns: void
- Outputs the pattern HTML directly
Example:
$this->render_block_pattern( 'hero-section' );
render_block_pattern_in_post_context( int $post_id, string $block_pattern_slug )
Renders a block pattern in the context of a specific post.
Parameters:
$post_id
(int) - The ID of the post to render the pattern in context of$block_pattern_slug
(string) - The slug of the pattern to render
Returns: void
- Outputs the pattern HTML directly
Example:
$this->render_block_pattern_in_post_context( 123, 'related-posts' );
Creating Reusable Block Patterns
Before using this trait, you need to create reusable block patterns in WordPress:
Method 1: Block Editor
- Create a new post with the "Reusable" block type
- Build your pattern using blocks
- Save it with a descriptive name
- The pattern will be available for selection
Method 2: Programmatically
<?php
// Create a reusable block programmatically
$pattern_content = '<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:heading {"textAlign":"center"} -->
<h2 class="wp-block-heading has-text-align-center">Hero Title</h2>
<!-- /wp:heading -->
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Hero description text goes here.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->';
$pattern_post = array(
'post_title' => 'Hero Section',
'post_content' => $pattern_content,
'post_status' => 'publish',
'post_type' => 'wp_block',
);
wp_insert_post( $pattern_post );
?>
Template Usage
Basic Pattern Rendering
<?php
$pattern_slug = $this->get_field( 'pattern' );
if ( ! empty( $pattern_slug ) ) {
?>
<div class="my-block__pattern">
<?php $this->render_block_pattern( $pattern_slug ); ?>
</div>
<?php
}
?>
Conditional Pattern Rendering
<?php
$pattern_slug = $this->get_field( 'pattern' );
$show_pattern = $this->get_field( 'show_pattern' );
if ( $show_pattern && ! empty( $pattern_slug ) ) {
?>
<div class="my-block__pattern my-block__pattern--<?php echo esc_attr( $pattern_slug ); ?>">
<?php $this->render_block_pattern( $pattern_slug ); ?>
</div>
<?php
}
?>
Multiple Pattern Support
<?php
$primary_pattern = $this->get_field( 'primary_pattern' );
$secondary_pattern = $this->get_field( 'secondary_pattern' );
?>
<div class="my-block">
<?php if ( ! empty( $primary_pattern ) ) : ?>
<div class="my-block__primary-pattern">
<?php $this->render_block_pattern( $primary_pattern ); ?>
</div>
<?php endif; ?>
<?php if ( ! empty( $secondary_pattern ) ) : ?>
<div class="my-block__secondary-pattern">
<?php $this->render_block_pattern( $secondary_pattern ); ?>
</div>
<?php endif; ?>
</div>
Use Cases
Content Blocks with Pattern Options
<?php
class Content_Block extends Block {
use Trait_Block_Pattern_Options;
protected function fields(): array {
return array(
array(
'key' => 'field_content_block_pattern',
'name' => 'content_pattern',
'label' => 'Content Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
'instructions' => 'Choose a predefined content pattern to display.',
),
);
}
}
Section Blocks with Multiple Patterns
<?php
class Section_Block extends Block {
use Trait_Block_Pattern_Options;
protected function fields(): array {
return array(
array(
'key' => 'field_section_header_pattern',
'name' => 'header_pattern',
'label' => 'Header Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
array(
'key' => 'field_section_footer_pattern',
'name' => 'footer_pattern',
'label' => 'Footer Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
);
}
}
Landing Page Blocks
<?php
class Landing_Page_Block extends Block {
use Trait_Block_Pattern_Options;
protected function fields(): array {
return array(
array(
'key' => 'field_landing_hero_pattern',
'name' => 'hero_pattern',
'label' => 'Hero Section Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
array(
'key' => 'field_landing_cta_pattern',
'name' => 'cta_pattern',
'label' => 'Call-to-Action Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
);
}
}
CSS Integration
Basic Pattern Styling
.my-block__pattern {
margin: 2rem 0;
// Style patterns within your block
.wp-block-group {
// Override default WordPress styles if needed
}
// Pattern-specific styling
&--hero-section {
background-color: var(--wp--preset--color--primary);
color: white;
padding: 3rem 0;
}
&--feature-grid {
background-color: var(--wp--preset--color--secondary);
padding: 2rem 0;
}
}
Responsive Pattern Handling
.my-block__pattern {
&--hero-section {
@media (max-width: 768px) {
padding: 2rem 0;
.wp-block-heading {
font-size: 1.5rem;
}
}
}
}
Advanced Usage
Dynamic Pattern Filtering
You can filter the available patterns using WordPress hooks:
<?php
// Filter patterns for a specific block
add_filter( 'block-my-block-pattern-choices', function( $choices ) {
// Only show certain patterns
$allowed_patterns = array( 'hero-section', 'feature-grid' );
return array_intersect_key( $choices, array_flip( $allowed_patterns ) );
});
?>
Pattern Context Switching
<?php
class Context_Aware_Block extends Block {
use Trait_Block_Pattern_Options;
protected function fields(): array {
return array(
array(
'key' => 'field_context_pattern',
'name' => 'context_pattern',
'label' => 'Context Pattern',
'type' => 'select',
'choices' => $this->get_block_pattern_choices(),
),
);
}
public function render() {
$pattern_slug = $this->get_field( 'context_pattern' );
if ( ! empty( $pattern_slug ) ) {
// Render pattern in current post context
$this->render_block_pattern_in_post_context( get_the_ID(), $pattern_slug );
}
}
}
?>
Error Handling
The trait gracefully handles various scenarios:
- No patterns available: Returns empty choices array
- Invalid pattern slug: Gracefully handles missing patterns
- Pattern rendering failure: Continues execution without breaking
- Database errors: Falls back gracefully
Best Practices
- Create meaningful patterns - Design patterns that serve specific purposes
- Keep patterns focused - Each pattern should have a single, clear purpose
- Test pattern rendering - Verify patterns work correctly in different contexts
- Document pattern usage - Let editors know when and how to use different patterns
- Consider performance - Large patterns may impact page load times
- Maintain consistency - Use patterns to ensure design consistency across the site
Common Pattern Types
- Hero Sections: Landing page headers with titles and CTAs
- Feature Grids: Product or service feature displays
- Testimonials: Customer feedback and reviews
- Contact Forms: Standardized contact information
- Navigation Elements: Consistent navigation components
- Footer Content: Standardized footer information