Add custom product field on quick edit option on the product listing of a woocommerce site - wordpress

How can I add custom product field/s on quick edit screen on the product listing of a woocommerce store?

I am not really sure if this is the best way to do it, but it works great for me
Basically my general goal is to add custom fields for a product, I managed to do it (Adding custom fields to the single product pages) with the help of these useful tuts.
http://www.remicorson.com/mastering-woocommerce-products-custom-fields/
http://www.remicorson.com/woocommerce-custom-fields-for-variations/
I recommend checking those links first before proceeding.
Now, what I wanted to do is to add those custom fields to the quick add option on the product listing.
That's where the resource get scarce.
Basically this is how I did it.
Add your custom field (the html forms) to the quick edit options.
I hooked into the 'woocommerce_product_quick_edit_end' action to accomplish this.
This hook is found on woocommerce->includes->admin->views->html-quick-edit-product.php on line 195
Save your custom field.
I hooked into the 'woocommerce_product_quick_edit_save' action to accomplish this.
This hook is found on woocommerce->includes->admin->class-wc-admin-post-types.php inside the 'quick_edit_save' function on line 929
The previous 2 steps does the trick, it does persist the values, however after updating the custom field via the quick edit option, the data is persisted on the backend, but is not populated to the custom field on the UI. That's why we need the 3rd step.
Add the custom field meta data inside the product listing column, then use js to extract the metadata out then populate it to the custom field
I hooked into the 'manage_product_posts_custom_column' action to add a custom HTML tags (div or whatever) to hold my custom field metadata
Then I used javascript to extract the data out from the meta data and populate it into the custom fields
Step 3 is just a copy of how WooCommerce does this process.
For referrence, take a look at function 'render_product_columns' of woocommerce->includes->admin->class-wc-admin-post-types.php
Also take a look at quick-edit.js located at woocommerce->assets->js->admin
Example Code:
Note that the code below is used for illustration and guide purposes, my actual code is quite long and complex.
Step 1:
add_action( 'woocommerce_product_quick_edit_end', function(){
/*
Notes:
Take a look at the name of the text field, '_custom_field_demo', that is the name of the custom field, basically its just a post meta
The value of the text field is blank, it is intentional
*/
?>
<div class="custom_field_demo">
<label class="alignleft">
<div class="title"><?php _e('Custom Field Demo', 'woocommerce' ); ?></div>
<input type="text" name="_custom_field_demo" class="text" placeholder="<?php _e( 'Custom Field Demo', 'woocommerce' ); ?>" value="">
</label>
</div>
<?php
} );
Step 2:
add_action('woocommerce_product_quick_edit_save', function($product){
/*
Notes:
$_REQUEST['_custom_field_demo'] -> the custom field we added above
Only save custom fields on quick edit option on appropriate product types (simple, etc..)
Custom fields are just post meta
*/
if ( $product->is_type('simple') || $product->is_type('external') ) {
$post_id = $product->id;
if ( isset( $_REQUEST['_custom_field_demo'] ) ) {
$customFieldDemo = trim(esc_attr( $_REQUEST['_custom_field_demo'] ));
// Do sanitation and Validation here
update_post_meta( $post_id, '_custom_field_demo', wc_clean( $customFieldDemo ) );
}
}
}, 10, 1);
Step 3:
add_action( 'manage_product_posts_custom_column', function($column,$post_id){
/*
Notes:
The 99 is just my OCD in action, I just want to make sure this callback gets executed after WooCommerce's
*/
switch ( $column ) {
case 'name' :
?>
<div class="hidden custom_field_demo_inline" id="custom_field_demo_inline_<?php echo $post_id; ?>">
<div id="_custom_field_demo"><?php echo get_post_meta($post_id,'_custom_field_demo',true); ?></div>
</div>
<?php
break;
default :
break;
}
}, 99, 2);
The JS part
jQuery(function(){
jQuery('#the-list').on('click', '.editinline', function(){
/**
* Extract metadata and put it as the value for the custom field form
*/
inlineEditPost.revert();
var post_id = jQuery(this).closest('tr').attr('id');
post_id = post_id.replace("post-", "");
var $cfd_inline_data = jQuery('#custom_field_demo_inline_' + post_id),
$wc_inline_data = jQuery('#woocommerce_inline_' + post_id );
jQuery('input[name="_custom_field_demo"]', '.inline-edit-row').val($cfd_inline_data.find("#_custom_field_demo").text());
/**
* Only show custom field for appropriate types of products (simple)
*/
var product_type = $wc_inline_data.find('.product_type').text();
if (product_type=='simple' || product_type=='external') {
jQuery('.custom_field_demo', '.inline-edit-row').show();
} else {
jQuery('.custom_field_demo', '.inline-edit-row').hide();
}
});
});
Make sure to enqueue the script
Hope this helps anyone, again, I am not sure if this is the best way to do it, but upon examining WooCommerce source, it seems WooCommerce
doesn't provide a convenient hook to accomplish this task with ease (at least not yet)
If you have a better approach than this please share.

Related

Print "custom label" for indicating type of post in the front end for Wordpress

I have a blog with different custom post types ("books", "interviews", "recipes", "events", etc...). those are all appearing in the home page with same format like a grid. I would like to print in the front end a "label" customized possibly, representing the kind/content of post.
For example:
if the post is a CPT "Book", I want to show in the grid cell "looking for a book?"
if the post is a CPT "Recipe", I want to show on same position, for specific post "hungry?"
etc...
Can you maybe help me in this? I guess I need some PHP code and set it with Elementor, but I am not a developer... :(
Thanks for any help.
Mario.
I have been asked in comment to put a screenshot. this is a fake grid taken from internet (I know, ugly layout), presenting in descending order by date all posts, very different in domain (different custom post types), which I am able to do it. What I need is, depending by Post Type, to add a slogan like "watch the movie" or "hungry?" or "Interview with...", a static string totally dependent by the type of CPT.
fake sample from internet
Further integration to explain the context.
See the current home page of my site: click here
You see two "posts" in a grid (3 columns, published with "post" widget in elementor and a custom skin. This custom skin is linked to a "loop" template created with "ele custom skin". As you see by the pic, you have one post which is a recipe (custom post type "Recipe") and one is a book (custom post type is book). But here I can eventually find also a standard post. Now, when you see the "red dot", I would like to put a word, which is directly dependent by the post type:
if "recipe" --> "Hungry?"
if "book" --> "our book reviews"...
etc...
as a sample I have in this link click here for each loop in the grid, called using "shortcode" widget
[helloworld]
and coded in snippets plugin following portion of php code
function HelloWorldShortcode() {
return '<p>Hello World!</p>';
}
add_shortcode('helloworld', 'HelloWorldShortcode');
Here is the code, from this code shortcode will be [vkh_display_post_tagline]
/**
* Custom shortcode to display the tagline by the post type.
*/
/**
* Custom shortcode to display the tagline by the post type.
*/
function vkh_display_tagline_by_post_type() {
global $post;
if ( ! $post || empty( $post ) ) {
return;
}
// Uncomment the next line for debugging and to know if we're getting post type of not.
// return $post->post_type;
$heading = '';
switch ( $post->post_type ) {
case 'recipe':
$heading = __( 'Hungry?', 'your-text-domain' );
break;
case 'book':
$heading = __( 'Our book reviews', 'your-text-domain' );
break;
// Add more cases following above examples.
default:
// If you have to assign anything default when a case doesn't match
// then write that here.
$heading = '';
break;
}
// When heading is not empty return heading within the html tag.
if ( ! empty( $heading ) ) {
return '<h4 class="post-tagline">' . esc_html( $heading ) . '</h4>';
}
}
add_shortcode( 'vkh_display_post_tagline', 'vkh_display_tagline_by_post_type' );

Woocommerce - Remove fields from woocommerce_form_field including validation

I am trying to customise the Woocommerce myaccount page, in particular the edit address page.
I want to display both the shipping + billing address forms on a single page. Ideally, in a single form with a one save button. I also need to remove a lot of the fields, so that it's a much simpler form of just an address (no name, company, etc).
I have implemented the code found on This Answer. It works nicely in that it shows both forms. However, I cannot remove the fields from the forms. If I try code like this:
add_filter( 'woocommerce_billing_fields' , 'custom_override_billing_fields' );
add_filter( 'woocommerce_shipping_fields' , 'custom_override_shipping_fields' );
function custom_override_billing_fields( $fields ) {
unset($fields['billing_country']);
unset($fields['billing_company']);
unset($fields['billing_first_name']);
unset($fields['billing_last_name']);
unset($fields['billing_phone']);
unset($fields['billing_email']);
return $fields;
}
function custom_override_shipping_fields( $fields ) {
unset($fields['shipping_country']);
unset($fields['shipping_company']);
unset($fields['shipping_first_name']);
unset($fields['shipping_last_name']);
return $fields;
}
It doesn't work, the fields are no longer shown but the form does not save on click... it just redirects to /my-account/edit-address/billing/ - and doesn't save. (the same form shown on this page doesn't save either).
I've also tried:
foreach ( $billing_fields as $key => $field ) :
if($key != 'billing_first_name' && $key != 'billing_last_name') :
woocommerce_form_field( $key, $field, $userMeta[$key][0] );
endif;
endforeach;
This removes the field from displaying, BUT the validation still exists - and any filter code I add to functions using
woocommerce_checkout_fields to remove the validation doesn't seem to affect this form at all.
Is there a way to either:
Remove fields from this form generated by woocommerce_form_field including the validation?
Create a custom form that allows me to set the input fields manually in the code, and update any fields that are there, ignoring the validation from Woocommerce completely?
This should work 100%. You need to state whether the fields you are removing is from billing or shipping and this is done by adding the ['billing'] or ['shipping'], whichever it is.
After this, adding the function directly to woocommerce_checkout_fields will apply both for billing and shipping.
For phone and company fields you can disable it in admin panel itself, do it.
Edit: And yes, all validation that was involved with the fields in the past will be removed. You can then apply any validation you need.
add_filter( 'woocommerce_checkout_fields' , 'brandimagemarketer_remove_billing_fields_checkout' );
function brandimagemarketer_remove_billing_fields_checkout( $fields ) {
unset($fields['billing']['billing_country']);
unset($fields['billing']['billing_first_name']);
unset($fields['billing']['billing_last_name']);
unset($fields['billing']['billing_email']);
unset($fields['shipping']['shipping_country']);
unset($fields['shipping']['shipping_first_name']);
unset($fields['shipping']['shipping_last_name']);
unset($fields['shipping']['shipping_email']);
return $fields;
}

How to get a Product Variation Custom Field to work along other plugins?

I get this code (see below) to create a Product Variation Custom Field. It works just fine. Now I need to use the WP All Import Pro plugin to import Products from a csv file. This plugin allow to create the importation task by mapping the information in the csv to the fields of Product and Product Variation.
Problem: thing is that the new created Product Variation Custom Field is not visible for the WP All Import plugin. I mean, this new field is not listed when I do the mapping of the data be imported.
My assumption is that this code fails to create some data in the database to make this field available for other module.
How can I get this to work properly
I also attached a capture of the WP All Import page where the field should be visible.
/*******************************
add custom fields to product variations
*********************************/
// regular variable products
add_action( 'woocommerce_product_after_variable_attributes', 'add_to_variations_metabox', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_product_variation', 20, 2 );
/*
* Add new inputs to each variation
*
* #param string $loop
* #param array $variation_data
* #return print HTML
*/
function add_to_variations_metabox( $loop, $variation_data, $variation ){
$custom = get_post_meta( $variation->ID, '_custom', true ); ?>
<div class="variable_custom_field">
<p class="form-row form-row-first">
<label><?php echo __( 'MY CUSTOM FIELD:', 'plugin_textdomain' ); ?></label>
<input type="text" size="5" name="variation_custom_data[<?php echo $loop; ?>]" value="<?php echo esc_attr( $custom ); ?>" />
</p>
</div>
<?php
}
/*
* Save extra meta info for variable products
*
* #param int $variation_id
* #param int $i
* return void
*/
function save_product_variation( $variation_id, $i ){
// save custom data
if ( isset( $_POST['variation_custom_data'][$i] ) ) {
// sanitize data in way that makes sense for your data type
$custom_data = ( trim( $_POST['variation_custom_data'][$i] ) === '' ) ? '' : sanitize_title( $_POST['variation_custom_data'][$i] );
update_post_meta( $variation_id, '_custom', $custom_data );
}
}
WP ALL IMPORT has this section coded into their files. They have not provide any hook or filter to add fields to this section.
The most important thing here is that WP ALL IMPORT has thought is like this :
As all the Meta for a particular variation is added finally to the post meta table. Which will be retrieved as by get_post_meta. Just like the custom fields. So in order to attach meta to the variation, you can just another Custom Fields with the Name as the name which the actual meta is stored with and with the value you want the variation to be. Just check the image attached. Refer - http://www.wpallimport.com/documentation/custom-fields/theme-plugin-fields/
I know this question was asked almost a year ago but I have been trying to figure out this exact issue out for quite some time now. But in the end I managed to find a workaround that at least will allow you to get that data into the variation instead of the main parent product:
1) In the WpAllImport Wordpress Addon you will be able to see a "variations" tab as shown in your screenshot. Click on this.
2) On this page you will once again not be able to see any custom fields you have made for variations HOWEVER there is a product attributes section.
3) If you add your variation as an attribute and uncheck "Show in variations" and "Taxonomy" and "Is Visible" then you can store your data in an attribute.
4) After the import you should be able to see you data in the attribute, if you know some programming you can even write a script to then loop through all variations and copy this data over to a custom field.
I know it's not much, but for my purposes I was at least able to save the data in the variation which I then used late in a product export plugin.
Hope that helps!
Though this question was initially asked 2 years ago. I found a solution in 2020. I hope this will help anyone who's still looking for a solution.
Please go to All Products and at the top where it says Add New Product you should see two more buttons "Import" and "Export". Click on Export and you will see an option of checkbox "Yes, export all custom meta" Please check this potion and all your custom fields even in variations will be exported.
Thanks

How to save meta boxes post meta?

I create this function for metaboxes and to save information, but I canĀ“t save the info and show it into the field.
My Code :
function reaction_buttons_meta2()
{
global $post;
$reaction_buttons_off2 = false;
if ( get_post_meta($post->ID, '_reaction_buttons_off2', true) ) {
$reaction_buttons_off = true;
}
update_post_meta($post->ID, 'reaction_buttons_off2', $_POST['reaction_buttons_off2']);
$meta=get_post_meta($post->ID, $field['reaction_buttons_off2'], true);
?>
<input type="text" id="reaction_buttons_off2" name="reaction_buttons_off2" value="<?php echo $meta[reaction_buttons_off2][0]; ?>">
<?php
}
function reaction_buttons_meta_box2()
{
add_meta_box('reaction_buttons2','Reaction Buttons','reaction_buttons_meta2','post','side');
add_meta_box('reaction_buttons2','Reaction Buttons','reaction_buttons_meta2','page','side');
}
add_action('admin_menu', 'reaction_buttons_meta_box2');
I need to put a simple field to store one option and after this show it in the template post.
I have never created meta boxes myself, but looking at your code all you do is trying to update meta but you need to add it first with add_post_meta.
Check this article on How To Create Custom Post Meta Boxes In WordPress.
For your issue, pay attention to Saving the meta box data section. As you can see, their function uses add_post_meta, update_post_meta and delete_post_meta functions.

Wordpress widget for post specific content in sidebar

I am looking for a wordpress plugin that will allow me to add a paragraph to the sidebar that is specific to the blog post. I would need to be able to add that text when creating the post. Is there something out there like that? I have been unsuccessful in searches.
Thanks
This can be easily solved using Custom Fields, the Text Widget and a Shortcode.
This bit of code goes in the theme's functions.php or, preferable, within a custom plugin.
1) Enable shortcodes for the Text Widget
add_filter( 'widget_text', 'do_shortcode' );
2) Define the shortcode, read comments for details
add_shortcode( 'mytext', 'so_13735174_custom_text_widget' );
function so_13735174_custom_text_widget( $atts, $content = null )
{
global $post;
// $post contains lots of info
// Using $post->ID many more can be retrieved
// Here, we are getting the Custom Field named "text"
$html = get_post_meta( $post->ID, 'text', true );
// Custom Field not set or empty, print nothing
if( !isset( $html ) || '' == $html )
return '';
// Print Custom Field
return $html;
}
3) Add a Text Widget in the desired sidebar.
Leave the title empty and put the Shortcode in the content: [mytext].
4) Now each page or post with a Custom Field named text will have its value printed in the Widget.
5) The $html can get fancy and multiple Custom Fields can be used.
This isn't something that I've ever personally done, but try this.
Summary: You will add the a paragraph using a custom field, then display it in a widget.
Details:
First, make sure custom fields are enabled. Edit a post, then click
the "screen options" at the top right of the page. If "Custom
Fields" isn't checked, check it. You should now see a custom field
area below the post editor.
Come up with a name for your custom field. Perhaps
"extra_paragraph". Now put that in the "name" field in the custom
field area.
Write your paragraph in the "value" field the custom field area.
Install the Custom Field Widget plugin, set it to display this
new "extra_paragraph" field. (widget appears to be untested with newer versions of Wordpress so cross your fingers!)
Now when you write or edit posts you should see this "extra_paragraph" field as an option in the "name" dropdown.

Resources