Support

Account

Home Forums Backend Issues (wp-admin) ACF on product variations: almost works

Solving

ACF on product variations: almost works

  • Hi,

    I managed to add custom fields to product variations with the piece of code bellow. Problem is variations are dynamically loaded when editing a product. Thus, even if custom fields are rendered the right way in the admin interface, JavaScript events are not attached to these fields, making things like gallery or image selector not to work or repeater not to react when trying to add a new entry.

    I would like to know if you know about a fix or workaround to make this work?

    Thanks.

    Code :

    $GLOBALS['wc_loop_variation_id'] = null;
    
    function is_field_group_for_variation($field_group, $variation_data, $variation_post) {
    	return (preg_match( '/Variation/i', $field_group['title'] ) == true);
    }
    
    add_action( 'woocommerce_product_after_variable_attributes', function( $loop_index, $variation_data, $variation_post ) {
    	$GLOBALS['wc_loop_variation_id'] = $variation_post->ID;
    
    	foreach ( acf_get_field_groups() as $field_group ) {
    		if ( is_field_group_for_variation( $field_group, $variation_data, $variation_post ) ) {
    			acf_render_fields( $variation_post->ID, acf_get_fields( $field_group ) );
    		}
    	}
    
    	$GLOBALS['wc_loop_variation_id'] = null;
    }, 10, 3 );
    
    add_action( 'woocommerce_save_product_variation', function( $variation_id, $loop_index ) {
    	if ( !isset( $_POST['acf_variation'][$variation_id] ) ) {
    		return;
    	}
    
    	$_POST['acf'] = $_POST['acf_variation'][$variation_id];
    
    	acf()->input->save_post( $variation_id );
    }, 10, 2 );
    
    add_filter( 'acf/prepare_field', function ( $field ) {
    	if ( !$GLOBALS['wc_loop_variation_id'] ) {
    		return $field;
    	}
    
    	$field['name'] = preg_replace( '/^acf\[/', 'acf_variation[' . $GLOBALS['wc_loop_variation_id'] . '][', $field['name'] );
    
    	return $field;
    }, 10, 1);
  • Found a solution for ACF fields requiring events to be attached.

    In your php code, add the following:

    function xxx_admin_head_post() {
    	global $post_type;
    	if ($post_type === 'product') {
    		wp_register_script( 'xxx-acf-variation', get_template_directory_uri() . '/js/acf-variation.js', array(
    			'jquery-core',
    			'jquery-ui-core'
    		), '1.1.0',
    			true ); // Custom scripts
    		
    		wp_enqueue_script( 'xxx-acf-variation' ); // Enqueue it!
    
    	}
    }
    
    /* actions fired when adding/editing posts or pages */
    /* admin_head-(hookname) */
    add_action( 'admin_head-post.php', 'xxx_admin_head_post' );
    add_action( 'admin_head-post-new.php',  'xxx_admin_head_post' );

    Create js/acf-variation.js with the following code:

    jQuery(document).ready(function($) {
        $( '#woocommerce-product-data' ).on( 'woocommerce_variations_loaded', function(){
            acf.doAction('ready');
        });
    });
  • Oups! “woocommerce_save_product_variation” action does not work properly.

    Replace with:

    add_action( 'woocommerce_save_product_variation', function( $variation_id, $loop_index ) {
    	if ( !isset( $_POST['acf_variation'][$variation_id] ) ) {
    		return;
    	}
    
    	if ( ! empty( $_POST['acf_variation'][$variation_id] ) && is_array( $fields = $_POST['acf_variation'][$variation_id] )  ) {
    		foreach ( $fields as $key => $val ) {
    			update_field( $key, $val, $variation_id );
    		}
    	}
    
    }, 10, 2 );
  • For some reason, when trying to use get_fields($variation_id) later (for example on front-end), you won’t be able to get the saved fields.

    This is quiet weird as update_field use to store fields seems to do the job the right way. Custom fields are saved in postmeta table : both field_name and _field_name are saves, the first with field value, the second with field key. Furthermore, these fields are restored the right way when editing product variations.

    For now, I have to use get_field('field_name', $variation_id) to get data.

  • I like to switch between product specs, when i change product variation.
    I should be nice if it is below the Description of Woocommerce.

    For example see Philips Lighting website.
    I want the specs of a LED Light switching when i change variation.
    Per lamp another specs below of the Description or a Tab.
    A table with with specs, copy and paste.

    Problem: When i make Product Type is Equal to Product Variation (WYSIWYG Editor). I don’t see the Editor at the Product Variation position.

  • null

  • @exnihilo_maxime I can add the fields but I cant save the data that I put in them. I just get an infinite spinner and the below error in the console:

    wp-admin/admin-ajax.php 500 (Internal Server Error)

    Any suggestions would be really appreciated.

    Thanks
    John

  • Hi @johnw6761.

    If you have a 500 internal server error, either there is a syntax error or something wrong occurs in the code (ex. trying to access a property on a non-objet variable).

    Could you please see if you find an error message in the latest fatal-errors-YYYY-MM-DD-*.log located in ./wp-content/uploads/wc-logs. Else, it won’t help much.

    Thanks.


    Maxime.

  • Hi @exnihilo_maxime .

    Thank you very much for your reply.

    This is the error shown in the logs:

    2019-09-17T07:57:27+00:00 CRITICAL Uncaught Error: Call to a member function save_post() on null in /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-content/themes/nevelli/functions/theme-support.php:148
    Stack trace:
    #0 /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-includes/class-wp-hook.php(286): {closure}(22, 0)
    #1 /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-includes/class-wp-hook.php(310): WP_Hook->apply_filters('', Array)
    #2 /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-includes/plugin.php(465): WP_Hook->do_action(Array)
    #3 /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-content/plugins/woocommerce/includes/admin/meta-boxes/class-wc-meta-box-product-data.php(532): do_action('woocommerce_sav...', 22, 0)
    #4 /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-content/plugins/woocommerce/includes/class-wc-ajax.php(2084): WC_Meta_Box_Product_Data::save_variations(14, Object(WP_Post))
    #5 /home/customer/www/ in /home/customer/www/nevelli.creativepatricktesting.co.uk/public_html/wp-content/themes/nevelli/functions/theme-support.php on line 148
    
    
  • Hi @johnw6761,

    I guess you are trying to call save_post() on $post or some other variable name. Make sure this variable exists. Maybe is $post (or other name) global. Did you try global $post; before you call save_post()?

  • Hi @exnihilo_maxime

    Im not sure i just used your code at the top of the page? I didnt add anything else? Was I supposed to?

    Thanks
    John

  • @johnw6761,

    Could you please copy-paste code in nevelli/functions/theme-support.php around line 148?

  • @exnihilo_maxime This is the whole code I am using

    $GLOBALS['wc_loop_variation_id'] = null;
    
    function is_field_group_for_variation($field_group, $variation_data, $variation_post) {
    	return (preg_match( '/Variation/i', $field_group['title'] ) == true);
    }
    
    add_action( 'woocommerce_product_after_variable_attributes', function( $loop_index, $variation_data, $variation_post ) {
    	$GLOBALS['wc_loop_variation_id'] = $variation_post->ID;
    
    	foreach ( acf_get_field_groups() as $field_group ) {
    		if ( is_field_group_for_variation( $field_group, $variation_data, $variation_post ) ) {
    			acf_render_fields( $variation_post->ID, acf_get_fields( $field_group ) );
    		}
    	}
    
    	$GLOBALS['wc_loop_variation_id'] = null;
    }, 10, 3 );
    
    add_action( 'woocommerce_save_product_variation', function( $variation_id, $loop_index ) {
    	if ( !isset( $_POST['acf_variation'][$variation_id] ) ) {
    		return;
    	}
    
    	$_POST['acf'] = $_POST['acf_variation'][$variation_id];
    
    	acf()->input->save_post( $variation_id );
    }, 10, 2 );
    
    add_filter( 'acf/prepare_field', function ( $field ) {
    	if ( !$GLOBALS['wc_loop_variation_id'] ) {
    		return $field;
    	}
    
    	$field['name'] = preg_replace( '/^acf\[/', 'acf_variation[' . $GLOBALS['wc_loop_variation_id'] . '][', $field['name'] );
    
    	return $field;
    }, 10, 1);
    

    and this is line 148
    acf()->input->save_post( $variation_id );

  • @johnw6761,

    This sounds weird. It’s like if acf() function was not existing or there was no input property. Sure ACF is activated?

  • @exnihilo_maxime

    Haha yes definitely activated, im pretty stupid but not that stupid lol.

    I did see on another thread someone else having the same issue.

  • @johnw6761

    Ha ha! 🙂 We never know. Well, strange issue. ACF being activated, the issue must be about input property. Did you try to print_r or var_dump it to see what’s in it?

  • @exnihilo_maxime

    In what sorry?

  • @johnw6761

    I missed the essential point: what to examine. Try to display what’s in acf()->input

    • Patrik

    • October 21, 2019 at 9:51 pm

    Any updates on this @exnihilo_maxime ? Did you come up with a “final” solution by chance?

    • onoweb

    • June 21, 2020 at 9:19 pm

    @johnw6761 @dekket you should replace the line
    acf()->input->save_post( $variation_id );
    with:
    do_action( 'acf/save_post', $variation_id );

    works for me, and looks like that is how it works behind the systems.

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

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.