Tag: Dynamic content in Gutenberg blocks

  • Day 17: Creating Server-Side Rendered Blocks in Gutenberg

    Introduction

    Welcome to Day 17 of the Gutenberg series! Today, we’ll cover server-side rendered blocks, which allow you to dynamically fetch and display content from the server, both in the editor and on the front end. Server-side blocks are particularly useful when you need to show real-time data, pull in posts, or display custom data from an external source.

    In this guide, you will learn how to:

    • Create a basic server-side rendered block.
    • Fetch and display dynamic content from WordPress.
    • Customize the rendering logic using PHP.

    What are Server-Side Rendered Blocks?

    Server-side rendered blocks allow you to generate content on the server side rather than the client side (in the browser). This means the block’s content is fetched or processed by the server every time the block is rendered in the editor or on the front end. This approach is ideal for blocks that display real-time data or content that may change frequently, such as:

    • Recent Posts: Display the latest posts dynamically.
    • Custom Post Data: Pull in specific data from custom post types or metadata.
    • External APIs: Fetch and display data from an external source, such as weather updates, stock prices, or RSS feeds.

    Step 1: Creating a Basic Server-Side Rendered Block

    Let’s start by creating a block that fetches and displays the latest posts from your WordPress site.

    1. Register the Block in JavaScript

    First, register the block in your JavaScript file (blocks/server-rendered-block.js). This block will use the ServerSideRender component to fetch content dynamically from the server.

    import { registerBlockType } from '@wordpress/blocks';
    import ServerSideRender from '@wordpress/server-side-render';
    
    registerBlockType('my-theme/latest-posts-block', {
        title: 'Latest Posts',
        icon: 'list-view',
        category: 'my-custom-category',
        edit: () => {
            return (
                <ServerSideRender
                    block="my-theme/latest-posts-block"
                />
            );
        },
        save: () => {
            return null; // Server-side block, no content saved
        },
    });
    

    Explanation:

    • ServerSideRender: This component automatically fetches the rendered block content from the server using the render_callback function in PHP.
    • save: null: Since this block is dynamically rendered on the server side, there’s no need to save any static content.

    Step 2: Adding the PHP Render Callback

    Next, we’ll define the logic for fetching the latest posts on the server side using PHP. This is where we’ll write the render_callback function.

    Add the following code to your theme’s functions.php file:

    function my_theme_render_latest_posts_block( $attributes ) {
        // Fetch the latest 5 posts
        $recent_posts = wp_get_recent_posts( array(
            'numberposts' => 5,
            'post_status' => 'publish',
        ) );
    
        if ( empty( $recent_posts ) ) {
            return '<p>No posts found.</p>';
        }
    
        $output = '<ul>';
        foreach ( $recent_posts as $post ) {
            $output .= sprintf(
                '<li><a href="%1$s">%2$s</a></li>',
                esc_url( get_permalink( $post['ID'] ) ),
                esc_html( get_the_title( $post['ID'] ) )
            );
        }
        $output .= '</ul>';
    
        return $output;
    }
    
    register_block_type( 'my-theme/latest-posts-block', array(
        'render_callback' => 'my_theme_render_latest_posts_block',
    ) );
    

    Explanation:

    • wp_get_recent_posts(): This function retrieves the latest posts from WordPress.
    • render_callback: This PHP function generates the block’s content dynamically and returns it as HTML to be displayed both in the editor and on the front end.

    Step 3: Customizing the Block with Attributes

    You can enhance the block’s functionality by allowing users to customize the number of posts displayed or other settings. Let’s add a control for adjusting the number of posts.

    1. Modify the JavaScript to Accept Block Attributes

    Update your JavaScript file to allow users to set the number of posts via the block settings.

    import { registerBlockType } from '@wordpress/blocks';
    import { InspectorControls } from '@wordpress/block-editor';
    import { PanelBody, RangeControl } from '@wordpress/components';
    import ServerSideRender from '@wordpress/server-side-render';
    
    registerBlockType('my-theme/latest-posts-block', {
        title: 'Latest Posts',
        icon: 'list-view',
        category: 'my-custom-category',
        attributes: {
            numberOfPosts: {
                type: 'number',
                default: 5,
            },
        },
        edit: ({ attributes, setAttributes }) => {
            const { numberOfPosts } = attributes;
    
            return (
                <>
                    <InspectorControls>
                        <PanelBody title="Settings">
                            <RangeControl
                                label="Number of Posts"
                                value={numberOfPosts}
                                onChange={(value) => setAttributes({ numberOfPosts: value })}
                                min={1}
                                max={10}
                            />
                        </PanelBody>
                    </InspectorControls>
                    <ServerSideRender
                        block="my-theme/latest-posts-block"
                        attributes={attributes}
                    />
                </>
            );
        },
        save: () => {
            return null; // Server-side block, no content saved
        },
    });
    

    Explanation:

    • attributes: We’ve added an attribute called numberOfPosts to control how many posts are displayed.
    • RangeControl: This component provides a slider for users to choose the number of posts (between 1 and 10).
    • InspectorControls: This allows the user to adjust settings in the block’s sidebar.

    Step 4: Updating the PHP Render Function to Handle Attributes

    Modify the PHP function to use the numberOfPosts attribute and dynamically display the specified number of posts.

    function my_theme_render_latest_posts_block( $attributes ) {
        $number_of_posts = isset( $attributes['numberOfPosts'] ) ? $attributes['numberOfPosts'] : 5;
    
        $recent_posts = wp_get_recent_posts( array(
            'numberposts' => $number_of_posts,
            'post_status' => 'publish',
        ) );
    
        if ( empty( $recent_posts ) ) {
            return '<p>No posts found.</p>';
        }
    
        $output = '<ul>';
        foreach ( $recent_posts as $post ) {
            $output .= sprintf(
                '<li><a href="%1$s">%2$s</a></li>',
                esc_url( get_permalink( $post['ID'] ) ),
                esc_html( get_the_title( $post['ID'] ) )
            );
        }
        $output .= '</ul>';
    
        return $output;
    }
    
    register_block_type( 'my-theme/latest-posts-block', array(
        'render_callback' => 'my_theme_render_latest_posts_block',
    ) );
    

    Explanation:

    • number_of_posts: We’ve updated the function to accept the numberOfPosts attribute and display the appropriate number of posts.

    Step 5: Testing the Server-Side Rendered Block

    1. Rebuild Your Block:
      • Run your build command to rebuild the block and ensure it’s loaded properly in the Block Editor.
    npm run build
    1. Test in the Editor:
      • Add the Latest Posts block to a post or page in the WordPress Block Editor.
      • Use the sidebar control to adjust the number of posts and observe how the block dynamically updates.
    2. Check Front-End Behavior:
      • Publish the post and verify that the correct number of latest posts is displayed on the front end.

    Best Practices for Server-Side Rendered Blocks

    1. Optimize Queries: When fetching data (e.g., posts or metadata), ensure that your queries are optimized to avoid performance issues, especially on high-traffic sites.
    2. Provide User Controls: Allow users to customize the block’s output via attributes, such as setting the number of items displayed or filtering content.
    3. Handle Empty States: Always provide fallback content (e.g., “No posts found”) to handle cases where there is no data to display.

    Conclusion: Leveraging Server-Side Rendering for Dynamic Content

    Server-side rendered blocks are powerful tools for dynamically displaying content in WordPress. Whether you’re pulling in posts, custom data, or external APIs, these blocks ensure that content is always up to date, both in the editor and on the front end. This approach is particularly useful for real-time data or frequently changing content like recent posts, latest products, or any type of dynamic feed.

    In this article, you’ve learned how to:

    • Create a basic server-side rendered block using the ServerSideRender component.
    • Fetch dynamic content from WordPress using the render_callback function in PHP.
    • Customize the block by adding user-configurable attributes.
    • Test server-side blocks both in the editor and on the front end.

    In Day 18, we’ll explore custom block transforms, which allow you to convert one block type into another, giving users more flexibility when editing content.

  • Day 15: Conditional Block Rendering in Gutenberg

    Introduction

    Welcome to Day 15 of the Gutenberg development series! Today, we’re diving into conditional block rendering. This technique allows you to control when and where blocks are displayed based on specific conditions, such as user roles, post metadata, or custom fields.

    For example, you could create a block that only shows content to logged-in users or display different content based on whether a post is marked as featured.

    In this guide, you’ll learn how to:

    • Implement conditional block rendering based on user roles.
    • Display blocks conditionally using post metadata or custom fields.
    • Dynamically control block visibility in the editor and on the front end.

    What is Conditional Block Rendering?

    Conditional block rendering means displaying a block only if certain conditions are met. This allows for more personalized content and dynamic user experiences. Common use cases include:

    • User Role-Based Rendering: Show specific content for logged-in users or administrators.
    • Post Metadata-Based Rendering: Display blocks only when certain metadata (e.g., a featured flag) is set.
    • Custom Field-Based Rendering: Show blocks based on values from custom fields or post types.

    This approach gives you greater control over what users see, ensuring the right content is displayed under the right circumstances.

    Step 1: Conditional Rendering Based on User Roles

    Let’s start by creating a block that only displays content to logged-in users or specific user roles (like administrators).

    PHP: Rendering Content Based on User Role

    In your block registration file (e.g., blocks/conditional-block.php), we’ll add logic to conditionally render the block’s content based on the user’s role.

    function my_theme_render_conditional_block( $attributes ) {
        if ( is_user_logged_in() ) {
            // Only show the block to logged-in users
            return '<div class="logged-in-content">Welcome, logged-in user!</div>';
        } else {
            // Show this message to users who are not logged in
            return '<div class="logged-out-content">Please log in to see the content.</div>';
        }
    }
    
    // Register the block with a conditional render callback
    function my_theme_register_conditional_block() {
        register_block_type( 'my-theme/conditional-block', array(
            'render_callback' => 'my_theme_render_conditional_block',
        ) );
    }
    add_action( 'init', 'my_theme_register_conditional_block' );

    Explanation:

    • is_user_logged_in(): This WordPress function checks if the user is logged in.
    • render_callback: The block’s render callback allows us to conditionally output content based on this check.

    With this setup, the block will display one message for logged-in users and a different message for visitors who aren’t logged in.

    Step 2: Conditional Rendering Based on Post Metadata

    Next, we’ll display blocks conditionally based on post metadata—specifically, whether the post is marked as featured.

    PHP: Rendering Content Based on Post Metadata

    We can use custom post meta fields to control the block’s visibility.

    function my_theme_render_metadata_block( $attributes ) {
        $post_id = get_the_ID();
        $is_featured = get_post_meta( $post_id, 'is_featured', true );
    
        if ( $is_featured ) {
            // Show the block only if the post is marked as featured
            return '<div class="featured-content">This is a featured post!</div>';
        } else {
            // Don't display anything if the post isn't featured
            return '';
        }
    }
    
    // Register the block with metadata-based conditional rendering
    function my_theme_register_metadata_block() {
        register_block_type( 'my-theme/metadata-conditional-block', array(
            'render_callback' => 'my_theme_render_metadata_block',
        ) );
    }
    add_action( 'init', 'my_theme_register_metadata_block' );

    Explanation:

    • get_post_meta(): Retrieves the value of the custom meta field is_featured for the current post.
    • Conditional Check: The block content is only shown if the post is marked as featured.

    Step 3: Conditional Rendering Using Custom Fields

    You can also control block visibility using custom fields. For example, let’s conditionally render a block based on a custom field called show_block.

    PHP: Rendering Content Based on Custom Fields

    function my_theme_render_custom_field_block( $attributes ) {
        $post_id = get_the_ID();
        $show_block = get_post_meta( $post_id, 'show_block', true );
    
        if ( $show_block ) {
            return '<div class="custom-field-content">This block is visible because the custom field is set!</div>';
        } else {
            return '';
        }
    }
    
    // Register the block with custom field-based conditional rendering
    function my_theme_register_custom_field_block() {
        register_block_type( 'my-theme/custom-field-conditional-block', array(
            'render_callback' => 'my_theme_render_custom_field_block',
        ) );
    }
    add_action( 'init', 'my_theme_register_custom_field_block' );

    Explanation:

    • Custom Field Check: The block is rendered based on the value of the show_block custom field, which is set in the post’s custom fields.

    Step 4: Implementing Conditional Rendering in the Block Editor

    To allow users to control block visibility conditions from the Block Editor, we can use Inspector Controls to add toggle switches or dropdowns for enabling or disabling content based on conditions.

    JavaScript: Adding Toggle Controls for Conditional Display

    In your block’s edit function, you can add an InspectorControls panel that allows the user to choose whether the block should display based on a condition.

    import { InspectorControls } from '@wordpress/block-editor';
    import { PanelBody, ToggleControl } from '@wordpress/components';
    import { registerBlockType } from '@wordpress/blocks';
    
    registerBlockType('my-theme/conditional-block', {
        title: 'Conditional Block',
        category: 'common',
        attributes: {
            showToLoggedInUsers: {
                type: 'boolean',
                default: false,
            },
        },
        edit: (props) => {
            const { attributes: { showToLoggedInUsers }, setAttributes } = props;
    
            return (
                <>
                    <InspectorControls>
                        <PanelBody title="Visibility Settings">
                            <ToggleControl
                                label="Show to Logged-in Users"
                                checked={showToLoggedInUsers}
                                onChange={(value) => setAttributes({ showToLoggedInUsers: value })}
                            />
                        </PanelBody>
                    </InspectorControls>
                    <div>{showToLoggedInUsers ? 'Visible to logged-in users' : 'Visible to all users'}</div>
                </>
            );
        },
        save: () => {
            return null; // Rendered server-side
        },
    });

    Explanation:

    • InspectorControls: Adds a toggle switch to the block settings in the editor, allowing users to control visibility.
    • ToggleControl: Lets users toggle whether the block is visible to logged-in users.

    Step 5: Testing the Conditional Blocks

    Once you’ve set up the conditional rendering logic, follow these steps to test your blocks:

    1. Rebuild Your Block: If you’re using a development environment, rebuild your block by running the appropriate command (e.g., npm run build).
    2. Test in the Editor: Go to the Block Editor and add your conditional blocks. Use the Inspector Controls to set visibility options.
    3. Check the Front End: Publish the post and view it on the front end to ensure the blocks display correctly based on the conditions you’ve set.

    Best Practices for Conditional Block Rendering

    1. Use Meaningful Conditions: Ensure that the conditions used for rendering are clear and make sense for the content. For example, role-based conditions should be intuitive for the user (e.g., showing admin-only content).
    2. Test Extensively: Test your conditional blocks with various user roles, metadata values, and dates to ensure that the rendering logic works across different scenarios.
    3. Consider Performance: Since conditional rendering often depends on server-side logic, ensure that your conditions are optimized to avoid performance bottlenecks, especially when querying post metadata or other dynamic data.

    Conclusion: Enhancing Flexibility with Conditional Block Rendering

    Conditional block rendering allows you to create highly flexible content layouts that adapt based on user roles, metadata, or custom logic. This feature enables more personalized content experiences, such as showing specific blocks to logged-in users or hiding content based on custom fields.

    In this article, you’ve learned how to:

    • Set up conditional block rendering based on user roles.
    • Use post metadata to control block visibility.
    • Apply custom logic to create dynamic rendering conditions.

    In Day 16, we’ll dive into interactive blocks, where we’ll explore how to create blocks that respond to user input, enhancing interactivity on your site.