Blog

  • How to Add Live Preview Updates to ACF Blocks in WordPress

    When building custom ACF blocks for WordPress, you might need the preview to update dynamically when editors change block settings. Here’s how to implement this functionality:

    The Problem

    By default, ACF blocks don’t automatically update their preview when field values change in the editor. If your block contains dynamic content (like a list of posts) that depends on block settings, you’ll need to handle these updates yourself.

    The Solution

    We’ll create a system that:

    1. Detects when block settings change
    2. Fetches updated content
    3. Updates the preview in real-time

    Implementation Steps

    1. Set Up Your Block Structure

    // block.json
    {
      "name": "acf/your-block",
      "title": "Your Block",
      "acf": {
        "mode": "preview",
        "renderTemplate": "template.php"
      }
    }

    2. Create a Base Class for Content Management

    class ContentManager {
        constructor(container) {
            this.container = container;
            this.contentContainer = container.querySelector('.content-container');
            // Initialize your content display logic
        }
    
        updateContent(data) {
            // Your content rendering logic
        }
    }

    3. Create a Centralized Fetch Function

    async function fetchContentFromServer(options, containers = {}) {
        const { container, contentContainer } = containers;
    
        // Handle loading states
        if (container) {
            if (container.dataset.isLoading === "true") return;
            container.dataset.isLoading = "true";
            if (contentContainer) {
                contentContainer.style.opacity = "0.5";
            }
        }
    
        try {
            const response = await fetch(ajaxurl, {
                method: "POST",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                },
                body: new URLSearchParams({
                    action: "your_action",
                    nonce: your_nonce,
                    ...options,
                }),
            });
    
            const data = await response.json();
            if (!data.success) {
                throw new Error(data.message || "Failed to fetch content");
            }
    
            return data.data;
        } finally {
            // Reset loading states
            if (container) {
                container.dataset.isLoading = "false";
                if (contentContainer) {
                    contentContainer.style.opacity = "1";
                }
            }
        }
    }

    4. Set Up Preview Handler

    function initializePreview(block) {
        if (!window.acf) return;
    
        // We only need to add this action once
        if (!initializePreview.initialized) {
            acf.addAction("render_block_preview", async function(block) {
                // Check if this is our block
                if (block[0]?.dataset?.type === "acf/your-block") {
                    const blockElement = block[0].querySelector(".your-block");
                    if (!blockElement) return;
    
                    // Create content manager instance
                    const contentManager = new ContentManager(blockElement);
    
                    // Get options from block data attributes
                    const options = {
                        setting1: blockElement.dataset.setting1,
                        setting2: blockElement.dataset.setting2,
                        preview: true
                    };
    
                    try {
                        const data = await fetchContentFromServer(
                            options,
                            {
                                container: blockElement,
                                contentContainer: blockElement.querySelector(".content-container")
                            }
                        );
                        contentManager.updateContent(data);
                    } catch (error) {
                        console.error("Preview update failed:", error);
                    }
                }
            });
            initializePreview.initialized = true;
        }
    }

    5. Initialize on Page Load

    window.addEventListener("load", function() {
        if (typeof acf === "undefined") return;
        initializePreview();
    });

    Key Points to Remember

    1. Use a class to manage content display logic – this keeps frontend and preview rendering consistent
    2. Centralize your fetch logic to handle both preview and frontend requests
    3. Use data attributes to pass settings from PHP to JavaScript
    4. Handle loading states and errors gracefully
    5. Only initialize preview handling once

    Common Pitfalls

    • Don’t create separate rendering logic for preview and frontend
    • Remember to handle loading states to prevent multiple simultaneous requests
    • Make sure your PHP template includes necessary data attributes
    • Consider error handling and fallback content
    • This pattern can be adapted for any ACF block that needs dynamic preview updates based on field changes.
  • Why Should You Care about WCAG 2.2 Conformance?

    Making sure your website is accessible isn’t just a nice-to-have; it’s crucial for creating an inclusive digital world. The Web Content Accessibility Guidelines (WCAG) 2.2 set the standards for ensuring accessibility for everyone, including individuals with disabilities. Here’s why you should care about WCAG 2.2 conformance:

    Inclusivity and Equal Access

    WCAG 2.2 helps make your website usable by everyone, regardless of their abilities. This means providing text alternatives for non-text content, ensuring content is easy to see and hear, and creating adaptable, keyboard-accessible interfaces.

    Legal Compliance

    Many countries, including the U.S., have laws requiring digital accessibility. Compliance with WCAG 2.2 helps you meet legal requirements and avoid potential lawsuits and fines.

    Enhanced User Experience

    Accessible websites are generally more user-friendly for everyone. Clear navigation, readable text, and keyboard accessibility not only help users with disabilities but also improve the overall user experience.

    Improved SEO

    Search engines like accessible websites. Following WCAG 2.2 guidelines can boost your site’s SEO, leading to better search engine rankings and increased traffic.

    Corporate Social Responsibility

    Demonstrating a commitment to accessibility reflects positively on your organization. It shows that you value all users and are committed to social responsibility, building trust and a positive reputation.

    Future-Proofing Your Website

    WCAG 2.2 provides a flexible framework that can adapt to future changes, ensuring your website remains accessible as technology evolves.

    Key Aspects of WCAG 2.2

    WCAG 2.2 focuses on four main principles:

    1. Perceivable: Making sure content is presented in ways users can perceive, such as providing text alternatives and making content easier to see and hear.
    2. Operable: Ensuring all functionality is accessible via a keyboard and allowing users enough time to interact with content.
    3. Understandable: Making text readable and predictable, and helping users avoid and correct mistakes.
    4. Robust: Ensuring content is compatible with a wide range of user agents and assistive technologies.

    Conclusion

    Conforming to WCAG 2.2 is a vital step in making your website accessible to all users. It enhances user experience, improves SEO, ensures legal compliance, and demonstrates your commitment to inclusivity and social responsibility. Embrace WCAG 2.2 to create a better digital experience for everyone.

    For more detailed information, check out AudioEye’s WCAG 2.2 Compliance Page.

  • How To Set Complex Element Attributes in Pinegrow Web Editor with PHP and WordPress Actions

    I needed to set the aria-label of my links with the post title, a custom field value and a hard-coded string. The default Pinegrow Set ACF Field action allows you to replace or append an attribute (in my case aria-label) with the field value, but the values are limited to custom fields, so it wasn’t ideal for my use case.

    My default link markup looked like this:

    <a href="https://rusmiller.com" target="_blank" rel="noreferrer noopener" aria-label="Job title:">WordPress Developer/Designer</a>

    I initially configured the Display ACF Field action like this:

    Settings for Display ACF Field in Pinegrow
    Settings for Display ACF Field in Pinegrow

    This produced the following markup:

    <a href="https://rusmiller.com" target="_blank" rel="noreferrer noopener" aria-label="Job title: WordPress Developer/Designer">WordPress Developer/Designer</a>

    This was great, but didn’t go far enough. So I removed the aria-label value Job title:, along with the ACF action, and added three PHP Code actions instead. In sequence, they retrieved the job_title field value and appended a dash, then appended the post title, and finally a bit of info informing the user that the link would open in another tab, then appended all to the default aria-label value.

    PHP Code configuration to append custom values to an HTML attribute
    PHP Code configuration to append custom values to an HTML attribute

    This produced the following markup:

    <a href="https://rusmiller.com" target="_blank" rel="noreferrer noopener" aria-label="WordPress Developer/Designer - Self-Employed (opens in a new tab)">WordPress Developer/Designer</a>