5

I am using the ACF plugin to manage a variety of custom meta data within a WooCommerce website. One of the features I'm trying to get set is to add custom fields to the WooCommerce checkout page. I am following the general concept outlined on WC's documentation page, which allows you to append custom forms to the WC checkout form via the woocommerce_after_order_notes hook. From there I'm inputting the acf form using the acf_form () function with form set to false to allow it to not include the ACF form elements (i.e. the ACF submit button). This seams to work because I'm successfully able to get the ACF custom fields to display on the checkout field in the appropriate location.

From there I'm attempting to use the ACF update_field() function in combination with the woocommerce_checkout_update_order_met hook. As recommended with the ACF community here. Here is my code that I have so far being placed in my functions.php file:

This part seams to work.

add_action( 'woocommerce_after_order_notes', 'my_custom_budgetcenter_field' ); //This runs the my_custom_budgetcenter_field funtion within the chekout form.

function my_custom_budgetcenter_field( ) { 
    echo '<div id="my_custom_budget center_field"><h2>' . __('Budget Center Field') . '</h2></div>'; // This Line Adds A header Line the the bottom of the WC Checkout Page. 
    acf_form(array('form' => false,'fields' => array('acf_selected_budget_center'))); //This line outputs the ACF form with form value set to false so its included in the woocommerce checkout form.  It then sets the fields to equal my the acf_selected_budget_center field group
}

This is the part that i'm having problems with:

add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_budgetcenter_field_update_order_meta' ); //This line runs the  my_custom_budgetcenter_field_update_order_meta when woocomerce updates the order meta when submiting the form.

function my_custom_budgetcenter_field_update_order_meta( $order_id ) { 
        $valueofbc = get_field( "field_5c005d0c5f829" );
        $bcfieldkey = "field_5c005d0c5f829";
        update_field( $bcfieldkey, $valueofbc, $order_id  );
    
} ;

When I manually set the $valueofbc string (Example: $valueofbc = "001 - Activities" ; ) everything works. I can submit an order and that field is updated with the hard coded string. However when I set it to the get_field function option so that it uses the ACF custom filed (a select value) it does not save the value. After doing some digging it looks like I need(ed) to set acf_form_head() above the wordpress get_header() function on the checkout page template inorder for ACF to pull and post the data. However when I did this and go through the checkout process and then click "submit order" on woocomerce' checkout page I get a "leave site? -- Changes you made may not be saved" -- Leave -- Cancel" JavaScript notice when the page attempts to process the order. When I click "Leave" it goes to the order confirmation page but does not save the meta value. When I click cancel the order processor just spins infitinatly and never refreshes the page.

At this point i'm at my witt's end trying to get this to work. I have to use ACF because of some advanced conditional logic on what is display and the way that data will work with other data in other forms. So using a basic checkout form add on plugin in not an option. Additionally ACF's support can take several weeks, which is why I'm posting here. Any help would be greatly appreciated.

Thanks,

Community
  • 1
  • 1
Andrew Glover
  • 192
  • 1
  • 9

3 Answers3

2

Figured it out. The acf_form_head() function is a combination of a number of actions. One of those actions (acf/submit_form) includes a redirect function that obviously doesn't work when submitting via another form. The solution is to use the acf/save_post action instead of the submit_form.

Andrew Glover
  • 192
  • 1
  • 9
  • Could you post the code you used to get this working. It's not clear to me where or how you updated which action the 'acf_form_head' should use 'acf/save_post' instead of 'acf/submit_form' – Benjamin Feb 03 '19 at 07:26
0

How to Update ACF Fields at Woocommerce Checkout

  1. Add your custom field to the checkout form using acf_form(). Hook in using 'woocommerce_after_order_notes':
add_action( 'woocommerce_after_order_notes', 'my_acf_checkout_display' ); 

function my_acf_checkout_display() { 
    acf_form(array('form' => false,'fields' => array('some_acf_field'))); 
}

NB: When calling acf_form() here, it is very important to set the 'form=false' in the arguments. Why? We want the ACF form data to run alongside the checkout form data -- so all data is passed in 'one' form.

And OP is correct, calling acf_form_head() on the checkout page will cause the checkout form to redirect. So leave out any acf_form_head() calls on the checkout page. If you're including acf_form_head() from another template, you can use this snippet:

  if (!is_checkout()) { acf_form_head(); }
  1. Update the custom field. Hook in using 'woocommerce_checkout_update_order_meta' to access the data, and update the custom field using ACF's update_field() method:
add_action( 'woocommerce_checkout_update_order_meta','acf_update_field_at_checkout' );
  
function acf_update_field_at_checkout( $order_id ) {
        
        // acf custom field id
        $my_field = 'field_63c8888f7bdce';

        $acf_form_value = $_POST['acf'][$my_field];

        update_field($my_field,$acf_form_value,$order_id);

}

Additional Comments

The only error OP made was trying to access the incoming value using the get_field() method:

$valueofbc = get_field( "field_5c005d0c5f829" );

Since our custom field data is being passed alongside the checkout data, we can access it in the $_POST variables. Updated example for accessing OP's incoming value:

$valueofbc = $_POST["acf"]["field_5c005d0c5f829"]

Finally, for Benjamin.. in the way this solution implements ACF custom fields at checkout, we don't need to write any custom code for what happens when 'acf/save_post' is called. The update_field() method takes care of the work (during woocommerce_checkout_update_order_meta), and 'acf/save_post' is called after the update is complete. (Also since our acf_form used form=false earlier, 'acf/submit_form' is never called). Generally, we only write custom code for these actions if we need to check/modify the data before/after it is saved. Hope this helps someone! Happy coding

0

This worked for me when updating a user field:

add_action( 'woocommerce_after_order_notes', 'my_acf_checkout_display' );

function my_acf_checkout_display() {
    acf_form(array('form' => false,'fields' => array('my-acf-field')));  
}

add_action( 'woocommerce_checkout_update_order_meta','acf_update_field_at_checkout' );

function acf_update_field_at_checkout( $order_id ) {
        $acf_form_value = $_POST['acf']['field_6420acfb79172'];
        $order = new WC_Order( $order_id );
        $user_id = $order->user_id;
        update_field('my-acf-field',$acf_form_value,'user_'.$user_id);
}
Dewayne
  • 3,682
  • 3
  • 25
  • 23