Support

Account

Forum Replies Created

  • CamiloAPR’s solution does indeed cause other ACF contexts to stop working, such as options, ACF blocks, etc.

    Here’s my solution that simply checks to see if the $post_id being passed in is for a “single” post along with is_preview() and otherwise doesn’t attempt to intervene:

    
    /**
     * Fix ACF post ID when previewing draft posts.
     *
     * In preview mode, WordPress uses the latest revision/autosave ID, which may not contain the updated ACF meta field data.
     *
     * This support thread got me halfway there, but it had to be modified to only interfere if the post ID is a single post, otherwise fields inside ACF blocks and other contexts don't work.
     * https://support.advancedcustomfields.com/forums/topic/preview-solution/page/3/#post-134967
     *
     * @param null|int $null    The value to return. If null, then the ACF plugin will figure out the context itself.
     * @param int      $post_id The "post ID" to check. Can be a post, but can also be any number of other ACF contexts.
     */
    function fix_acf_post_id_on_preview( $null, $post_id ) {
    	// Only intervene if the post_id is a single post and we're in preview mode.
    	if ( is_single( $post_id ) && is_preview() ) {
    		// Get the actual post ID instead of the current revision ID.
    		return get_the_ID();
    	}
    
    	return $null;
    }
    add_filter( 'acf/pre_load_post_id', 'fix_acf_post_id_on_preview', 10, 2 );
    
  • I’ve successfully filtered the block registration to include the SVG icon with custom foreground color. Note that I had to bump up the priority of the enqueue action to 9 in order for the filter to apply; maybe there is a better way of doing it. Also note that the SVG element is not a string; you’ll need to have a workflow set up like what wp-scripts provides.

    The code below is within a custom plugin.

    acf-filter.js

    
    const { addFilter } = wp.hooks;
    
    /**
     * ACF Custom SVG Icon filter
     *
     * ACF detects an SVG string for icon but not icon['src']
     */
    addFilter(
    	'blocks.registerBlockType',
    	'cr0ybot/acf-block-icons',
    	( settings, name ) => {
    		if ( name === 'acf/my-block' ) {
    			settings.icon = {
    				foreground: '#7bb12d',
    				src: <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0,0H24V24H0Z" fill="none"/><polygon points="20 18 4 18 4 20 20 20 20 18"/><path d="M22,3H2A1,1,0,0,0,1,4V15a1,1,0,0,0,1,1H22a1,1,0,0,0,1-1V4A1,1,0,0,0,22,3ZM21,5V9.92l-3.38-2.7a1,1,0,0,0-1.24,0L12,10.74,8.6,8.2a1,1,0,0,0-1.15,0L3,11.13V5ZM3,14v-.46l5-3.32L11.4,12.8a1,1,0,0,0,1.22,0L17,9.28l4,3.2V14Z"/></svg>,
    			};
    		}
    
    		return settings;
    	}
    );
    

    plugin.php

    
    function cr0ybot_block_editor_enqueue_assets() {
    	wp_enqueue_script(
    		'cr0ybot-block-filter',
    		plugins_url( '/acf-filter.js', __FILE__ ),
    	);
    }
    add_action( 'enqueue_block_editor_assets', 'cr0ybot_block_editor_enqueue_assets', 9 );
    
    
  • Just a small update, the acf-block-icon plugin is not actually working for me.

    I did a little digging into the ACF code and it looks like a string starting with <svg is being detected, but only for the icon property and not if you’ve set the icon via icon['src']. I was setting my icon like this because I want to have a custom foreground color:

    
    acf_register_block_type( array(
        // ...
        'icon' => array(
            'foreground' => '#7bb12d',
            'src' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0,0H24V24H0Z" fill="none"/><polygon points="20 18 4 18 4 20 20 20 20 18"/><path d="M22,3H2A1,1,0,0,0,1,4V15a1,1,0,0,0,1,1H22a1,1,0,0,0,1-1V4A1,1,0,0,0,22,3ZM21,5V9.92l-3.38-2.7a1,1,0,0,0-1.24,0L12,10.74,8.6,8.2a1,1,0,0,0-1.15,0L3,11.13V5ZM3,14v-.46l5-3.32L11.4,12.8a1,1,0,0,0,1.22,0L17,9.28l4,3.2V14Z"/></svg>',
    ),
    

    I’m looking to see if I can add a filter via JS on blocks.registerBlockType to handle the icon with foreground color for the time being.

  • Don’t use uniqid() with the same input and expect different output on consecutive calls within a for/while loop—see https://www.php.net/manual/en/function.uniqid.php#120123.

    The uniqid() function is part of the standard PHP library and has no relation or knowledge of ACF, and so does not in any way set “a variable by pulling the ACF unique ID of a repeater in a flex block” as @pierrebalian claims. It simply outputs a “random” string based on the current microseconds and any seed you feed it.

    If you must use uniquid() at least feed it some value from your repeater within the loop so that you can reasonably expect it to be different each time. Both @pierrebalian and @waynep16 are generating a single random string once and outputting it within the loop, which will obviously output the same value each time.

    The better option is to use a hashing function like md5() along with serialize() to not only generate unique strings, but also ensure that they are the same id each page load. This method creates a hash for the full repeater/flexible content field row. You can also use substr() to reduce the length to something manageable, like 8 characters, and still be reasonably sure that you’ll get unique values each time.

    
    <?php
    $rows = array();
    while ( have_rows( 'repeater_or_flex_content' ) ) : $row = the_row(true); // pass true to get formatted subfields
    	$id = substr( md5( serialize( $row ) ), 0, 8 ); // outputs something like '35f841ff'
    	$rows[$id] = $row; // store the $row for use elsewhere with the id
    ?>
    	<div id="panel-<?php echo $id; ?>" aria-labeledby="tab-<?php echo $id; ?>" role="tabpanel">
    		<?php the_sub_field( 'tab_content' ); ?>
    	</div>
    <?php
    endwhile;
    
    // Later, when building tabs
    foreach ( $rows as $r ) :
    ?>
    	<button id="tab-<?php echo $r['id]; ?>" role="tab" aria-controls="panel-<?php echo $r['id']; ?>"><?php echo $r['tab_title']; ?></button>
    <?php
    endforeach;
    

    Of course you can reverse this approach so you’re outputting tabs first, storing the rows, and using them later to output the tab content, but hopefully you get the gist.

  • Don’t use uniqid() with the same input and expect different output on consecutive calls within a for/while loop—see https://www.php.net/manual/en/function.uniqid.php#120123.

    The uniqid() function is part of the standard PHP library and has no relation or knowledge of ACF, and so does not in any way set “a variable by pulling the ACF unique ID of a repeater in a flex block” as @pierrebalian claims. It simply outputs a “random” string based on the current microseconds and any seed you feed it.

    If you must use uniquid() at least feed it some value from your repeater within the loop so that you can reasonably expect it to be different each time. Both @pierrebalian and @waynep16 are generating a single random string once and outputting it within the loop, which will obviously output the same value each time.

    The better option is to use a hashing function like md5() along with serialize() to not only generate unique strings, but also ensure that they are the same id each page load. This method creates a hash for the full repeater/flexible content field row. You can also use substr() to reduce the length to something manageable, like 8 characters, and still be reasonably sure that you’ll get unique values each time.

    
    <?php
    $rows = array();
    while ( have_rows( 'repeater_or_flex_content' ) ) : $row = the_row(true); // pass true to get formatted subfields
    	$id = substr( md5( serialize( $row ) ), 0, 8 ); // outputs something like '35f841ff'
    	$rows[$id] = $row; // store the $row for use elsewhere with the id
    ?>
    	<div id="panel-<?php echo $id; ?>" aria-labeledby="tab-<?php echo $id; ?>" role="tabpanel">
    		<?php the_sub_field( 'tab_content' ); ?>
    	</div>
    <?php
    endwhile;
    
    // Later, when building tabs
    foreach ( $rows as $r ) :
    ?>
    	<button id="tab-<?php echo $r['id]; ?>" role="tab" aria-controls="panel-<?php echo $r['id']; ?>"><?php echo $r['tab_title']; ?></button>
    <?php
    endforeach;
    

    Of course you can reverse this approach so you’re outputting tabs first, storing the rows, and using them later to output the tab content, but hopefully you get the gist.

Viewing 5 posts - 1 through 5 (of 5 total)