Search code examples
wordpressadvanced-custom-fieldsacfpro

ACF Repeater Field on Product Variations


Using the following code to add ACF to individual product variations as per here and here. Everything seems to be displaying properly, except for a repeater field:

// Add product variations ACF rule
add_filter('acf/location/rule_values/post_type', 'acf_location_rule_values_Post');
function acf_location_rule_values_Post( $choices ) {
    $choices['product_variation'] = 'Product Variation';
    return $choices;
}

$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);

When adding a row on the repeater field, it does not appear.

Then I get the following javascript error upon product save, repeated for however many times I click "Add row":

An invalid form control with name='acf_variation[37][field_5db9a1722bbe2][field_5db9a1de2bbe5][acfcloneindex][field_5db9a1ed2bbe6]' is not focusable.

When I inspect only one table row is there, with class="acf-row acf-clone". ACF's stylesheets show:

.acf-repeater .acf-row.acf-clone {
    display: none !important;
}

When I add admin styles:

.acf-repeater .acf-row.acf-clone {
    display: table-row !important;
}

the first field displays but other fields still do not get added (both in display and to the DOM while inspecting. Any ideas?


Solution

  • Add script after rendering the field:

    function rdv__after__render_field( $field ){
        //add these if you want to apply it on certain fields only 
        //if ($field['key'] != 'field_key') {
        //    return;
        //}
        echo "<script>
                (function($) {
                    acf.doAction('append', $('#post'));
                })(jQuery);
              </script>";
    }
    add_action( 'acf/render_field/type=repeater', 'rdv__after__render_field', 10, 1 );
    

    and then change your 'woocommerce_save_product_variation' (got this piece on https://support.advancedcustomfields.com/forums/topic/acf-on-product-variations-almost-works/) to

    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 );