28

I've been trying to add a single text input field to every item in the cart and submit that user input to product's meta info. It's been 2 days and I haven't succeeded yet.

My objective is to:

  1. Take input from user for every item added to the cart.
  2. Display that input in the order's meta info.
  3. Display that input in confirmation email sent to the customer.

So far, I have copied the template file to my theme and added an input field inside a cell. I'm having trouble with the hooks, learned about hooks I will need from WooCommerce Product Gift Wrap plugin as indicated in this woocommerce issue.

Code I added to the cart.php template copied in my theme directory :

$input_url_data = '<div class="input-url"><input type="text" name="cart-url" value="" title="" class="input-text cart-url text" /></div>';

echo apply_filters( 'woocommerce_add_cart_item_data', $input_url_data, $cart_item_key );

Code I added to my theme's functions.php :

add_filter( 'woocommerce_add_cart_item_data','add_cart_item_data', 10, 2 );
add_filter( 'woocommerce_get_cart_item_from_session','get_cart_item_from_session', 10, 2 );
add_filter( 'woocommerce_get_item_data','get_item_data', 10, 2 );
add_filter( 'woocommerce_add_cart_item','add_cart_item', 10, 1 );
add_action( 'woocommerce_add_order_item_meta','add_order_item_meta', 10, 2 );

function add_cart_item_data( $cart_item_meta, $product_id ) {
    $input_url_key = "";
    $input_url_data['inputurl'] = $input_url_key;
    return $input_url_data;
}

function get_cart_item_from_session( $cart_item, $values ) {

if ( ! empty( $values['inputurl'] ) ) {
    $cart_item['inputurl'] = true;
}
return $cart_item;
}

function get_item_data( $item_data, $cart_item ) {

if ( ! empty( $cart_item['inputurl'] ) )
    $item_data[] = array(
    );
return $item_data;
}

function add_cart_item( $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) ) {

}
return $cart_item;
}

function add_order_item_meta( $item_id, $cart_item ) {
if ( ! empty( $cart_item['inputurl'] ) )
woocommerce_add_order_item_meta( $item_id, __( 'URL by buyer', 'custom_input_url' ), __( 'Yes', 'custom_input_url' ) );
}

Documentation about hook woocommerce_add_cart_item_data isn't very helpful and I'm stuck at this. How do I proceed?

Nix
  • 500
  • 1
  • 4
  • 19
  • Maybe you can use some jQuery to create an array of product name/field and then on submit send an Ajax request to a processing/validation page that does a table lookup for the product name, finds that products id, then from there you can do an insert into the product meta field with that ID and then the field that was created. Just an idea since my answer below doesn't work in your particular situation. – Ian Feb 13 '14 at 18:43

3 Answers3

23

There is a wordpress plugin called WC Fields Factory for the exact purpose.

You can also achieve this by using the following woocommerce hooks woocommerce_before_add_to_cart_button, woocommerce_add_to_cart, woocommerce_cart_item_name,and 'woocommerce_add_order_item_meta'

like for adding text field to product page

function add_name_on_tshirt_field() {
  echo '<table class="variations" cellspacing="0">
      <tbody>
          <tr>
          <td class="label"><label for="color">Name On T-Shirt</label></td>
          <td class="value">
              <input type="text" name="name-on-tshirt" value="" />
          </td>
      </tr>                             
      </tbody>
  </table>';
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_name_on_tshirt_field' );

For displaying custom field on cart item table use the below

function render_meta_on_cart_item( $title = null, $cart_item = null, $cart_item_key = null ) {
    if( $cart_item_key && is_cart() ) {
        echo $title. '<dl class="">
                 <dt class="">Name On T-Shirt : </dt>
                 <dd class=""><p>'. WC()->session->get( $cart_item_key.'_name_on_tshirt') .'</p></dd>           
              </dl>';
    }else {
        echo $title;
    }
}
add_filter( 'woocommerce_cart_item_name', 'render_meta_on_cart_item', 1, 3 );

to make your custom meta data on you order details, do some thing like this

function tshirt_order_meta_handler( $item_id, $values, $cart_item_key ) {
    wc_add_order_item_meta( $item_id, "name_on_tshirt", WC()->session->get( $cart_item_key.'_name_on_tshirt') );    
}
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 1, 3 );

for detailed implementation, i have an article about how to do this without using any plugins. http://sarkware.com/how-to-pass-custom-data-to-cart-line-item-in-woocommerce-without-using-plugins/

Sark
  • 4,458
  • 5
  • 26
  • 25
8

It's easy. Try searching and reading code of Woocommerce.

This much of code got me to point where I can add Url @ Cart. And I can see it in Order review as customer and as admin.

I can't test email because I'm lazy. I'm sorry.

Something like this goes in templates\cart\cart.php (there is need for some more code as it's seperate column)

<td class="product-url">
    <?php
        $html = sprintf( '<div class="url"><input type="text" name="cart[%s][url]" value="%s" size="4" title="Url" class="input-text url text" /></div>', $cart_item_key, esc_attr( $values['url'] ) );
        echo $html;
    ?>
</td>

Functions.php

// get from session your URL variable and add it to item
add_filter('woocommerce_get_cart_item_from_session', 'cart_item_from_session', 99, 3);
function cart_item_from_session( $data, $values, $key ) {
    $data['url'] = isset( $values['url'] ) ? $values['url'] : '';
    return $data;
}

// this one does the same as woocommerce_update_cart_action() in plugins\woocommerce\woocommerce-functions.php
// but with your URL variable
// this might not be the best way but it works
add_action( 'init', 'update_cart_action', 9);
function update_cart_action() {
    global $woocommerce;
    if ( ( ! empty( $_POST['update_cart'] ) || ! empty( $_POST['proceed'] ) ) && $woocommerce->verify_nonce('cart')) {
        $cart_totals = isset( $_POST['cart'] ) ? $_POST['cart'] : '';
        if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
            foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
                if ( isset( $cart_totals[ $cart_item_key ]['url'] ) ) {
                    $woocommerce->cart->cart_contents[ $cart_item_key ]['url'] = $cart_totals[ $cart_item_key ]['url'];
                }
            }
        }
    }
}

// this is in Order summary. It show Url variable under product name. Same place where Variations are shown.
add_filter( 'woocommerce_get_item_data', 'item_data', 10, 2 );
function item_data( $data, $cart_item ) {
    if ( isset( $cart_item['url'] ) ) {
        $data['url'] = array('name' => 'Url', 'value' => $cart_item['url']);
    }
    return $data;
}

// this adds Url as meta in Order for item
add_action ('woocommerce_add_order_item_meta', 'add_item_meta', 10, 2);
function add_item_meta( $item_id, $values ) {
    woocommerce_add_order_item_meta( $item_id, 'Url', $values['url'] );
}

400$ is nice price.

ViszinisA
  • 462
  • 7
  • 14
  • Hey, thanks for the answer. I have a requirement to get another input from customer on cart page (for every item) and I think your answer will be suitable for that as well. Bounty was going to expire so thought should give it to you first and then mess with the template (I've already copied and alter cart.php in my theme's folder). Will try it and I think adding the URL info to the email template will work the same way as adding to order item meta, will give that a shot as well. Thanks. – Nix Feb 16 '14 at 23:20
  • @Nix If it doesn't work just post some comment. Or open new thread with updated code and PM me the url. – ViszinisA Feb 16 '14 at 23:38
  • Sure thing. Although I'm not aware how to send messages on Stackoverflow. Thanks :) – Nix Feb 16 '14 at 23:41
  • Ups. It appears that you can't. My mistake. My twitter is same as my user name. – ViszinisA Feb 16 '14 at 23:51
  • Thanks. I tested the code, it did display the additional field, but for some reason not displaying the input. I'm trying to figure that out now, will keep posted. – Nix Feb 17 '14 at 18:04
  • this code works fine but do not work on the proceed to checkout button click – Sunil Verma Mar 19 '15 at 13:52
0

You can do this fairly easily with the Woocommerce Product Add-ons plugin

From the WooThemes website:

Allow your customers to customise your products by adding new options such as input boxes, dropdowns or checkboxes. With the Product Add-ons extension, gift messages, donations, laser engraving and any other product which may require user input in some way is now an option for your customers!

Product add-ons supports required fields, textareas, checkboxes, radios, select boxes, custom price inputs and file upload boxes.

I've used it before to add an additional donation field to a product purchase and display that on the thank you page/receipt email.

It's about $50 US and will get you up and running in no time to add the text input and display the field on thank you page/email like you want. $50 is definitely worth the amount of time you'd save drying to develop this feature yourself.

Here's the flow from the end-users perspective:

End user enters in field data and adds product to cart End User enters in field data and adds product to cart

When User views cart the data they entered into the custom field displays along with the product When User views cart the data they entered into the custom field displays along with the product

After purchase, end user lands on thank you page and receives receipt email with field data included with the product item. After purchase, end user lands on thank you page and receives receipt email with field data included with the product item.

On the backend:

Create custom field for each product. The option is located on the Add-Ons menu tab.

  1. Create a new Addon Group
  2. Enter a group name (for easier organization)
  3. Add a new option and enter the label (this is what the end user sees and is tied to the product)
  4. Update/Publish product.

Create custom field for each product

For completed orders, this is what you will see in the Order Details admin:

product order details page also displays the field

Hope this helps and saves you a ton of time in development!

Ian
  • 3,266
  • 4
  • 29
  • 37
  • Hi, yes, I bought this plugin for my past project, but this client has specifically asked me to disable product pages and archive pages. I'm adding products using variations and attributes directly from pricing tables. So his requirement is to edit the input box particularly in the cart itself and that too for every item in the cart. – Nix Feb 13 '14 at 18:33
  • Bummer. That's a strange request. You are right, my answer doesn't help in your particular situation. I haven't heard of any similar situations. I'll follow this thread, let us know if you get it working. – Ian Feb 13 '14 at 18:39
  • Thanks pal. I have been in touch with several woo-affiliated agencies and woocommerce "experts" from my country (India) regarding this. I mulling over getting this extension made (got a quote of $400), use it in this project and then put it on Envato marketplace. I believe there are other people who have the same requirement as it reduces the number of steps (good for UX) and is useful when there are fewer products. – Nix Feb 13 '14 at 18:45
  • Nope. Let me know if you have. – Nix Oct 19 '14 at 17:15