Reputation: 301
Good day.
Is there a way to add input fields to a product in WooCommerce dynamically based on the amount of products selected?
I have found many solutions where there can be static fields, but none where it updates automatically. For example, if I have 3 quantity in the product page, to add a name, cell number and email address for each product and is a required field.
The options I have seen are:
https://wordpress.org/plugins/woo-checkout-field-editor-pro/
https://wordpress.org/plugins/wc-fields-factory/
Upvotes: 4
Views: 5241
Reputation: 663
Based on @HMagby answer, my version manages multiple fields for each item in cart and for each quantity.
Field values are saved as order item meta
after the order is placed. Ideal for ticketing eCommerce.
<?php
class MRL_Utils
{
private $products_ids = false;
private $personal_data = false;
public function __construct()
{
// Campi
$this->personal_data = array(
"nome" => array("label" => "Nome", "type" => "text", "class" => "my-field-class form-row-first", "required" => true, "placeholder" => "Inserisci il nome del partecipante"),
'tel' => array("label" => "Cellulare", "type" => "tel", "class" => "my-field-class form-row-last", "required" => false, "placeholder" => "Inserisci il numero di cellulare"),
'note' => array("label" => "Intolleranze e/o allergie", "type" => "textarea", "class" => "my-field-class form-row-wide", "required" => false, "placeholder" => "Specifica eventuali intolleranze e/o allergie"),
);
$this->products_ids = array(32, 33, 34, 35);
// Form nella pagina del Checkout
add_action('woocommerce_before_order_notes', array($this, 'mrl_display_personal_data_field'), 10, 1);
add_action('woocommerce_checkout_update_order_meta', array($this, 'mrl_save_personal_data_field'), 10, 1);
}
public function mrl_save_personal_data_field($order_id)
{
$order = wc_get_order($order_id);
foreach($order->get_items() as $item_id => $item)
{
$product_id = $item->get_product_id();
$quantity = $item->get_quantity();
// Procedo solo se il prodotto è tra quelli abilitati
if(in_array($product_id, $this->products_ids))
{
// Salvo i dati inseriti come dei meta per ogni item dell'ordine
// Ricordiamoci che c'è un solo ITEM anche se la quantità è > 1
for($i = 0; $i < $quantity; $i++)
{
// So che i dati sono salvati in questo modo: mrl_NAME_ID_#
// Dove NAME è la key di $_POST, ID è l'ID del prodotto a catalogo e # è progressivo da 0 a quantità
$valori = array();
// Per ogni dato personale
foreach($this->personal_data as $key => $value)
{
$label = $value['label'];
$selettore = "mrl_".$key."_".$product_id."_".$i;
if(isset($_POST[$selettore]))
{
$valori[$label] = $_POST[$selettore];
}
}
// Salvo i meta dell'item
$valori = implode(', ', array_map(
function ($v, $k) { return sprintf("%s: %s", $k, $v); },
$valori,
array_keys($valori)
));
wc_add_order_item_meta($item_id, "#".($i+1), $valori, true);
wc_update_order_item_meta($item_id, "#".($i+1), $valori);
}
}
}
}
public function mrl_display_personal_data_field($checkout)
{
global $woocommerce;
$items = $woocommerce->cart->get_cart();
foreach($items as $item => $values)
{
// Ogni item avrà una sua quantità
$qty = $values['quantity'];
$_id = $values['data']->get_id();
$_product = wc_get_product($_id);
$title = $_product->get_title();
// Procedo solo se il prodotto è tra quelli abilitati
if(in_array($_id, $this->products_ids))
{
echo "<h3>$title ($qty)</h3>";
for($i = 0; $i < $qty; $i++)
{
echo "<div style='border:5px solid var(--ast-global-color-2);padding:10px;margin-top:10px;margin-bottom:10px;background-color:#fafafa'><h4>#".($i+1)."</h4>";
// Per ogni dato personale
foreach($this->personal_data as $key => $value)
{
$type = $value['type'];
$label = $value['label'];
$class = $value['class'];
$required = $value['required'];
$placeholder = $value['placeholder'];
$selettore = "mrl_".$key."_".$_id."_".$i;
woocommerce_form_field($selettore, array(
'type' => $type,
'class' => array($class),
'label' => $label." #".($i+1),
'placeholder' => $placeholder,
'required' => $required,
),
$checkout->get_value($selettore),
);
}
echo "</div>";
}
}
}
}
}
add_action('plugins_loaded', function(){
new MRL_Utils();
});
?>
Upvotes: 0
Reputation: 3285
Let’s say you have a booking system on your WooCommerce store and you want to capture the additional information at checkout if someone books for more than one quantity. For e.g., if you have Events/Workshops site and want to capture Name, Email, phone, and Address of everyone who attended your Event/Workshop and someone books for 3 quantity on your website then you need additional dynamic custom fields to capture the details of other 2 attendees. So if someone adds 3 quantity to the cart then the checkout page adds additional fields for other 2 attendees if 4 quantity added to the cart then it adds fields for other 3 attendees.
Within the following function, we will check how many quantities the user has in their cart and adds the additional fields to the checkout page if the quantity is more than 1. And save the field values to display it in the order in admin side.
Go to your functions.php file and add the following code at the end of the file or you can create your own plugin to add this function.
//Custom WooCommerce Checkout Fields based on Quantity
add_action( 'woocommerce_before_order_notes', 'person_details' );
function person_details($checkout) {
global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
$i = 1;
for($k=2; $k<= $count; $k++) {
$i++;
print ('<h3>Please enter details of attendee '.$i.'</h3>');
woocommerce_form_field( 'cstm_full_name'.$i, array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('Full name'),
'placeholder' => __('Enter full name'),
),
$checkout->get_value( 'cstm_full_name'.$i ));
echo '<div class="clear"></div>';
woocommerce_form_field( 'cstm_phone'.$i, array(
'type' => 'text',
'class' => array('my-field-class form-row-first'),
'label' => __('Phone'),
'placeholder' => __('Enter phone number'),
),
$checkout->get_value( 'cstm_phone'.$i ));
woocommerce_form_field( 'cstm_email'.$i, array(
'type' => 'email',
'class' => array('my-field-class form-row-last'),
'label' => __('Email address'),
'placeholder' => __('Enter email address'),
),
$checkout->get_value( 'cstm_email'.$i ));
echo '<div class="clear"></div>';
woocommerce_form_field( 'cstm_address'.$i, array(
'type' => 'textarea',
'class' => array('my-field-class form-row-wide'),
'label' => __('Full address'),
'placeholder' => __('Enter full address'),
),
$checkout->get_value( 'cstm_address'.$i ));
}
}
/**
* Save value of fields
*/
add_action('woocommerce_checkout_update_order_meta', 'customise_checkout_field_update_order_meta');
function customise_checkout_field_update_order_meta($order_id)
{
global $woocommerce;
$count = $woocommerce->cart->cart_contents_count;
$i = 1;
for($k=2; $k<= $count; $k++) {
$i++;
if (!empty($_POST['cstm_full_name'.$i])) {
update_post_meta($order_id, 'Name of Attendee'.$i, sanitize_text_field($_POST['cstm_full_name'.$i]));
}
if (!empty($_POST['cstm_phone'.$i])) {
update_post_meta($order_id, 'Phone of Attendee'.$i, sanitize_text_field($_POST['cstm_phone'.$i]));
}
if (!empty($_POST['cstm_email'.$i])) {
update_post_meta($order_id, 'Email of Attendee'.$i, sanitize_text_field($_POST['cstm_email'.$i]));
}
if (!empty($_POST['cstm_address'.$i])) {
update_post_meta($order_id, 'Address of Attendee'.$i, sanitize_text_field($_POST['cstm_address'.$i]));
}
}
}
Dynamic custom fields on checkout page
Custom Fields value on order page in admin
Upvotes: 4