woocommerce creating checkbox with multiple choises [duplicate] - php

Ive been trying to add a custom field in woocommerce backend where users can multiselect checkboxes for a certain level.
Is it possible to create multiple checkboxes? So far i have this:
woocommerce_wp_checkbox(
array(
'id' => '_custom_product_niveau_field',
'type' => 'checkbox',
'label' => __('Niveau', 'woocommerce'),
'options' => array(
'MBO' => __( 'MBO', 'woocommerce' ),
'HBO' => __( 'HBO', 'woocommerce' ),
'WO' => __( 'WO', 'woocommerce' )
)
)
But that doesnt work... Does woocommerce_wp_checkbox have support for this?

2021 Update
2021 Update - Solved issues with:
• in_array() where 2nd argument was a string on start*.
• $thepostid as in some cases it was empty.
That is possible creating a custom function this way:
// New Multi Checkbox field for woocommerce backend
function woocommerce_wp_multi_checkbox( $field ) {
global $thepostid, $post;
if( ! $thepostid ) {
$thepostid = $post->ID;
}
$field['value'] = get_post_meta( $thepostid, $field['id'], true );
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['style'] = isset( $field['style'] ) ? $field['style'] : '';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = isset( $field['value'] ) ? $field['value'] : array();
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['desc_tip'] = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
echo '<fieldset class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
<legend>' . wp_kses_post( $field['label'] ) . '</legend>';
if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
echo wc_help_tip( $field['description'] );
}
echo '<ul class="wc-radios">';
foreach ( $field['options'] as $key => $value ) {
echo '<li><label><input
name="' . esc_attr( $field['name'] ) . '"
value="' . esc_attr( $key ) . '"
type="checkbox"
class="' . esc_attr( $field['class'] ) . '"
style="' . esc_attr( $field['style'] ) . '"
' . ( is_array( $field['value'] ) && in_array( $key, $field['value'] ) ? 'checked="checked"' : '' ) . ' /> ' . esc_html( $value ) . '</label>
</li>';
}
echo '</ul>';
if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
echo '</fieldset>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Multi Select fields in Woocommerce backend
Usage example (for a simple product):
// Add custom multi-checkbox field for product general option settings
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_settings_fields', 20 );
function add_custom_settings_fields() {
global $post;
echo '<div class="options_group hide_if_variable"">'; // Hidding in variable products
woocommerce_wp_multi_checkbox( array(
'id' => '_custom_level',
'name' => '_custom_level[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'MBO' => __( 'MBO', 'woocommerce' ),
'HBO' => __( 'HBO', 'woocommerce' ),
'WO' => __( 'WO', 'woocommerce' )
)
) );
echo '</div>';
}
// Save custom multi-checkbox fields to database when submitted in Backend (for all other product types)
add_action( 'woocommerce_process_product_meta', 'save_product_options_custom_fields', 30, 1 );
function save_product_options_custom_fields( $post_id ){
if( isset( $_POST['_custom_level'] ) ){
$post_data = $_POST['_custom_level'];
// Data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $post_id, '_custom_level', $sanitize_data );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The selected values are correctly saved and displayed. For info the value is an array.

Related

how to change a normal dropdown to an auto populating dropdown on wooocomerce product page

I am working on setting up a woocommerce shop.
We have a requirement where the customer would be able to choose a product and when a product is chosen, a subsequent dropdown would be populated with the variants of the products. When the variant is chosen the price would be displayed
I am able to change the tag to a , but the functionality is breaking and the dependency between two is lost.
Please advise on how I may be able to use a data list instead of a dropdowns while maintain the product/variant conditions
Example – 50 US states in first datalist and the second data list to list the counties for that state and when the county is selected the pricing would be shown
Wordpress Version - 5.8
Woocommerce Version - 6.4.1
Below is the code that I am trying version to fix. Please advise if this is right of I use another option or a plugin that could help
if ( ! function_exists( 'wc_dropdown_variation_attribute_options' ) ) {
/**
* Output a list of variation attributes for use in the cart forms.
*
* #param array $args Arguments.
* #since 2.4.0
*/
function wc_dropdown_variation_attribute_options( $args = array() ) {
$args = wp_parse_args(
apply_filters( 'woocommerce_dropdown_variation_attribute_options_args', $args ),
array(
'options' => false,
'attribute' => false,
'product' => false,
'selected' => false,
'name' => '',
'id' => '',
'class' => '',
'show_option_none' => __( 'Choose an option', 'woocommerce' ),
)
);
// Get selected value.
if ( false === $args['selected'] && $args['attribute'] && $args['product'] instanceof WC_Product ) {
$selected_key = 'attribute_' . sanitize_title( $args['attribute'] );
// phpcs:disable WordPress.Security.NonceVerification.Recommended
$args['selected'] = isset( $_REQUEST[ $selected_key ] ) ? wc_clean( wp_unslash( $_REQUEST[ $selected_key ] ) ) : $args['product']->get_variation_default_attribute( $args['attribute'] );
// phpcs:enable WordPress.Security.NonceVerification.Recommended
}
$options = $args['options'];
$product = $args['product'];
$attribute = $args['attribute'];
$name = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id = $args['id'] ? $args['id'] : sanitize_title( $attribute );
$class = $args['class'];
$show_option_none = (bool) $args['show_option_none'];
$show_option_none_text = $args['show_option_none'] ? $args['show_option_none'] : __( 'Choose an option', 'woocommerce' );
if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
$attributes = $product->get_variation_attributes();
$options = $attributes[ $attribute ];
}
$html = '<input list="' . ( $id ) . '"class="' . esc_attr( $class ) . '" name="' . esc_attr( $name ) . '" data-attribute_name="attribute_' . esc_attr( sanitize_title( $attribute ) ) . '" data-show_option_none="' . ( $show_option_none ? 'yes' : 'no' ) . '">';
$html .= '<datalist id="' . esc_attr( $id ) . '" >';
$html .= '<option value="">' . esc_html( $show_option_none_text ) . '</option>';
if ( ! empty( $options ) ) {
if ( $product && taxonomy_exists( $attribute ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms(
$product->get_id(),
$attribute,
array(
'fields' => 'all',
)
);
foreach ( $terms as $term ) {
if ( in_array( $term->slug, $options, true ) ) {
$html .= '<option value="' . esc_attr( $term->slug ) . '" ' . selected( sanitize_title( $args['selected'] ), $term->slug, false ) . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name, $term, $attribute, $product ) ) . '</option>';
}
}
} else {
foreach ( $options as $option ) {
// This handles < 2.4.0 bw compatibility where text attributes were not sanitized.
$selected = sanitize_title( $args['selected'] ) === $args['selected'] ? selected( $args['selected'], sanitize_title( $option ), false ) : selected( $args['selected'], $option, false );
$html .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $option, null, $attribute, $product ) ) . '</option>';
}
}
}
$html .= '</datalist>';
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo apply_filters( 'woocommerce_dropdown_variation_attribute_options_html', $html, $args );
}
}

Issue with saving value from Select2 field in WooCommerce backend

I'm using a code to initial a select2 field in WooCommerce Backend. The selecting field is working good, but I have problems after saving product.
I cannot get the value from db and be pre-selected. Also can not save it as well.
Can anybody give a tip with this? Should data be saved as an array?
My code:
function woocommerce_wp_product_select2( $field ) {
global $thepostid, $post, $woocommerce;
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="wc-product-search ' . esc_attr( $field['class'] ) . '" multiple="multiple" data-maximum-selection-length="1">';
foreach ( $field['value'][0] as $key => $value ) {
echo '<option value="'.$value.'" selected="selected">'.wc_get_product( $value )->name.' (#'.$value.')</option>';
}
echo '</select> ';
if ( ! empty( $field['description'] ) ) {
if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
echo '<span class="woocommerce-help-tip" data-tip="' . esc_attr( $field['description'] ) . '"></span>';
} else {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
}
echo '</p>';
}
add_filter( 'woocommerce_product_data_tabs', 'kyatipov_promo_tab', 10, 1 );
function kyatipov_promo_tab($default_tabs) {
$default_tabs['promo'] = array(
'label' => __( 'Промоция', 'domain' ),
'target' => 'kyatipov_promo_tab_content',
'priority' => 60,
'class' => array('promo-tab-produkti')
);
return $default_tabs;
}
add_action( 'woocommerce_product_data_panels', 'kyatipov_promo_tab_content' );
function kyatipov_promo_tab_content() {
global $woocommerce, $post;
?>
<div id="kyatipov_promo_tab_content" class="panel woocommerce_options_panel">
<style>
#woocommerce-product-data ul li.promo_options.promo_tab.promo-tab-produkti a::before {
font-family: Dashicons;
content: "\f198";
}
h4#ízbran-produkt, h4#iztrii-izbran-prod {
margin-left: 12px;
}
.iztrii-container {
display: flex;
}
h4#iztrii-izbran-prod::after {
font-family: Dashicons;
content: "\f182";
color: red;
font-size: 26px;
}
h4#iztrii-izbran-prod {
margin-top: 0;
}
h4#iztrii-izbran-prod:hover {
cursor: -webkit-grabbing; cursor: grabbing;
}
select#wc_product_ids + span.select2 {
width: 350px !IMPORTANT;
}
</style>
<?php
woocommerce_wp_checkbox( array(
'id' => '_enable_promo_for_current_product',
//'wrapper_class' => 'show_if_simple',
'label' => __( 'Включи промо', 'woocommerce' ),
'description' => __( 'Тази опция е задължителна, ако желаете да ползвате промо фу-ота за този продукт!', 'my_text_domain' ),
'default' => '0',
'desc_tip' => true,
) );
$save_data = get_post_meta( $post->ID, 'wc_product_ids' );
echo $save_data;
print_r($save_data);
woocommerce_wp_product_select2([
'id' => 'wc_product_ids',
'label' => __( 'Продукт', 'woocommerce' ),
'class' => '',
'name' => 'wc_product_ids[]',
'value' => $save_data,
'desc_tip' => true,
'description' => __( 'Избери продукт за промоция', 'wc' ),
]);
echo '</div>';
}
// Save Meta
add_action('woocommerce_process_product_meta', 'kyatipov_custom_field_save');
function kyatipov_custom_field_save( $post_id ){
// Select
$izbran_promo_prod = $_POST['wc_product_ids'];
if( !empty( $izbran_promo_prod ) )
update_post_meta( $post_id, 'wc_product_ids', esc_attr( $izbran_promo_prod ) );
$izbran_promo_prod2 = $_POST['save_data'];
if( !empty( $izbran_promo_prod2 ) )
update_post_meta( $post_id, 'save_data', esc_attr( $izbran_promo_prod2 ) );
}
First of all I modified the woocommerce_wp_product_select2() function you are using:
I've added $field['placeholder'] to the function, so that a placeholder can be used if desired
data-exclude="<?php echo $thepostid; ?>" has been added so that the current product cannot be selected
$field['value'] = ! empty( $field['value'] ) ? $field['value'] : array(); was also added to the function, to avoid an error message when the metadata does not exist/do not yet exist
When it comes to saving, you're making the mistake that esc_attr() is used with an array, while it expects a string
p.s. to save fields you can use the woocommerce_admin_process_product_object hook, opposite the outdated woocommerce_process_product_meta hook
So you get:
function woocommerce_wp_product_select2( $field ) {
global $thepostid, $post;
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['placeholder'] = isset( $field['placeholder'] ) ? $field['placeholder'] : '';
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = ! empty( $field['value'] ) ? $field['value'] : array();
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="wc-product-search ' . esc_attr( $field['class'] ) . '" multiple="multiple" style="width: 50%;" data-maximum-selection-length="1" data-placeholder="' . esc_attr( $field['placeholder'] ) . '" data-exclude="<?php echo $thepostid; ?>" >';
foreach ( $field['value'] as $key => $value ) {
$product = wc_get_product( $value );
if ( is_object( $product ) ) {
echo '<option value="' . esc_attr( $value ) . '"' . selected( true, true, false ) . '>' . esc_html( wp_strip_all_tags( $product->get_formatted_name() ) ) . '</option>';
}
}
echo '</select> ';
if ( ! empty( $field['description'] ) ) {
if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
echo '<span class="woocommerce-help-tip" data-tip="' . esc_attr( $field['description'] ) . '"></span>';
} else {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
}
echo '</p>';
}
function filter_woocommerce_product_data_tabs( $default_tabs ) {
$default_tabs['promo'] = array(
'label' => __( 'Промоция', 'domain' ),
'target' => 'kyatipov_promo_tab_content',
'priority' => 60,
'class' => array( 'promo-tab-produkti' )
);
return $default_tabs;
}
add_filter( 'woocommerce_product_data_tabs', 'filter_woocommerce_product_data_tabs', 10, 1 );
function action_woocommerce_product_data_panels() {
global $post;
echo '<div id="kyatipov_promo_tab_content" class="panel woocommerce_options_panel">';
// Get data
$data = get_post_meta( $post->ID, '_wc_product_ids', true );
// Add field via custom function
woocommerce_wp_product_select2(
array(
'id' => 'wc_product_ids',
'label' => __( 'Продукт', 'woocommerce' ),
'placeholder' => __( 'My placeholder', 'woocommerce' ),
'class' => '',
'name' => 'wc_product_ids[]',
'value' => $data,
'desc_tip' => true,
'description' => __( 'Избери продукт за промоция', 'woocommerce' ),
)
);
echo '</div>';
}
add_action( 'woocommerce_product_data_panels', 'action_woocommerce_product_data_panels' );
// Save
function action_woocommerce_admin_process_product_object( $product ) {
// Good idea to make sure things are set before using them
$data = isset( $_POST['wc_product_ids'] ) ? (array) $_POST['wc_product_ids'] : array();
// Update
$product->update_meta_data( '_wc_product_ids', array_map( 'esc_attr', $data ) );
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
Related: Add custom select2 search field into WooCommerce product data metabox

woocommerce creating checkbox with multiple choises doesnt work [duplicate]

Ive been trying to add a custom field in woocommerce backend where users can multiselect checkboxes for a certain level.
Is it possible to create multiple checkboxes? So far i have this:
woocommerce_wp_checkbox(
array(
'id' => '_custom_product_niveau_field',
'type' => 'checkbox',
'label' => __('Niveau', 'woocommerce'),
'options' => array(
'MBO' => __( 'MBO', 'woocommerce' ),
'HBO' => __( 'HBO', 'woocommerce' ),
'WO' => __( 'WO', 'woocommerce' )
)
)
But that doesnt work... Does woocommerce_wp_checkbox have support for this?
2021 Update
2021 Update - Solved issues with:
• in_array() where 2nd argument was a string on start*.
• $thepostid as in some cases it was empty.
That is possible creating a custom function this way:
// New Multi Checkbox field for woocommerce backend
function woocommerce_wp_multi_checkbox( $field ) {
global $thepostid, $post;
if( ! $thepostid ) {
$thepostid = $post->ID;
}
$field['value'] = get_post_meta( $thepostid, $field['id'], true );
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['style'] = isset( $field['style'] ) ? $field['style'] : '';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = isset( $field['value'] ) ? $field['value'] : array();
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['desc_tip'] = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
echo '<fieldset class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
<legend>' . wp_kses_post( $field['label'] ) . '</legend>';
if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
echo wc_help_tip( $field['description'] );
}
echo '<ul class="wc-radios">';
foreach ( $field['options'] as $key => $value ) {
echo '<li><label><input
name="' . esc_attr( $field['name'] ) . '"
value="' . esc_attr( $key ) . '"
type="checkbox"
class="' . esc_attr( $field['class'] ) . '"
style="' . esc_attr( $field['style'] ) . '"
' . ( is_array( $field['value'] ) && in_array( $key, $field['value'] ) ? 'checked="checked"' : '' ) . ' /> ' . esc_html( $value ) . '</label>
</li>';
}
echo '</ul>';
if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
echo '</fieldset>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Multi Select fields in Woocommerce backend
Usage example (for a simple product):
// Add custom multi-checkbox field for product general option settings
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_settings_fields', 20 );
function add_custom_settings_fields() {
global $post;
echo '<div class="options_group hide_if_variable"">'; // Hidding in variable products
woocommerce_wp_multi_checkbox( array(
'id' => '_custom_level',
'name' => '_custom_level[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'MBO' => __( 'MBO', 'woocommerce' ),
'HBO' => __( 'HBO', 'woocommerce' ),
'WO' => __( 'WO', 'woocommerce' )
)
) );
echo '</div>';
}
// Save custom multi-checkbox fields to database when submitted in Backend (for all other product types)
add_action( 'woocommerce_process_product_meta', 'save_product_options_custom_fields', 30, 1 );
function save_product_options_custom_fields( $post_id ){
if( isset( $_POST['_custom_level'] ) ){
$post_data = $_POST['_custom_level'];
// Data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $post_id, '_custom_level', $sanitize_data );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The selected values are correctly saved and displayed. For info the value is an array.

Metabox with multi checkbox in WooCommerce admin single orders

I added successfully a Metabox with a multi checkbox field that is displayed on admin single order pages and works perfectly.
I am using Multi checkbox fields in Woocommerce backend answer code for that multi checkbox.
// Adding Meta container admin shop_order pages
add_action( 'add_meta_boxes', 'em_add_meta_boxes' );
if ( ! function_exists( 'em_add_meta_boxes' ) )
{
function em_add_meta_boxes()
{
add_meta_box( 'em_other_fields', __('Employee Extra Actions','woocommerce'), 'em_add_other_fields_for_order_empl', 'shop_order', 'side', 'core' );
}
}
// Adding Meta field in the meta container admin shop_order pages
if ( ! function_exists( 'em_add_other_fields_for_order_empl' ) )
{
function em_add_other_fields_for_order_empl()
{
global $post;
echo '<div class="options_group">';
woocommerce_wp_multi_checkbox( array(
'id' => 'employee_actions12',
'name' => 'employee_actions12[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'tee' => __( 'MBO', 'woocommerce' ),
'saa' => __( 'HBO', 'woocommerce' ),
'tee1' => __( 'WO', 'woocommerce' ),
)
) );
echo '</div>';
}
}
Final part of code is to save at database, Here is it:
add_action( 'save_post', 'save_product_options_custom_fields32', 30, 1 );
function save_product_options_custom_fields32( $post_id ){
if( isset( $_POST['employee_actions12'] ) ){
$post_data = $_POST['employee_actions12'];
// Multi data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $post_id, 'employee_actions12', $sanitize_data );
}
}
I know code works for product pages with action: 'woocommerce_product_process_meta'
So, i need help for saving at db, an fixing error notice for array (i think this can happen if we select default value).
There was another issue with the function woocommerce_wp_multi_checkbox() that I have updated again (when used in a custom metabox).
I have also revisited all your code, specially the last function that saves the multi-checkboxes selected values.
The complete code:
// WooCommerce admin custom multi checkbox field function
function woocommerce_wp_multi_checkbox( $field ) {
global $thepostid, $post;
if( ! $thepostid ) {
$thepostid = $post->ID;
}
$field['value'] = get_post_meta( $thepostid, $field['id'], true );
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['style'] = isset( $field['style'] ) ? $field['style'] : '';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['value'] = isset( $field['value'] ) ? $field['value'] : array();
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['desc_tip'] = isset( $field['desc_tip'] ) ? $field['desc_tip'] : false;
echo '<fieldset class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '">
<legend>' . wp_kses_post( $field['label'] ) . '</legend>';
if ( ! empty( $field['description'] ) && false !== $field['desc_tip'] ) {
echo wc_help_tip( $field['description'] );
}
echo '<ul class="wc-radios">';
foreach ( $field['options'] as $key => $value ) {
echo '<li><label><input
name="' . esc_attr( $field['name'] ) . '"
value="' . esc_attr( $key ) . '"
type="checkbox"
class="' . esc_attr( $field['class'] ) . '"
style="' . esc_attr( $field['style'] ) . '"
' . ( is_array( $field['value'] ) && in_array( $key, $field['value'] ) ? 'checked="checked"' : '' ) . ' /> ' . esc_html( $value ) . '</label>
</li>';
}
echo '</ul>';
if ( ! empty( $field['description'] ) && false === $field['desc_tip'] ) {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
echo '</fieldset>';
}
// Adding a custom Metabox on WooCommerce single orders
add_action( 'add_meta_boxes', 'add_custom_shop_order_metabox' );
function add_custom_shop_order_metabox(){
add_meta_box(
'custom_shop_order_metabox',
__('Employee Extra Actions', 'woocommerce'),
'content_custom_shop_order_metabox',
'shop_order',
'side',
'core'
);
}
// Custom Metabox content on WooCommerce single orders
function content_custom_shop_order_metabox() {
global $thepostid, $post;
echo '<div class="options_group">';
woocommerce_wp_multi_checkbox( array(
'id' => 'employee_actions12',
'name' => 'employee_actions12[]',
'label' => __('Levels', 'woocommerce'),
'options' => array(
'tee' => __( 'MBO', 'woocommerce' ),
'saa' => __( 'HBO', 'woocommerce' ),
'tee1' => __( 'WO', 'woocommerce' ),
),
) );
echo '</div>';
}
// Save WooCommerce single orders Custom Metabox field values
add_action( 'save_post_shop_order', 'save_custom_shop_order_metabox_field_values' );
function save_custom_shop_order_metabox_field_values( $post_id ){
if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
|| ! current_user_can( 'edit_shop_order', $post_id ) ) {
return;
}
if( isset( $_POST['employee_actions12'] ) ){
update_post_meta( $post_id, 'employee_actions12', wc_clean($_POST['employee_actions12']) );
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Multi Select fields in Woocommerce backend

I am trying to create 4 multi-select options at Woocommerce product variations.
For example: I am selling trees and want to display the season the tree is available. So we have 4 seasons (spring, summer, autumn, winter), Some trees are available in two or tree seasons.
I added this code to my functions.php, but it won't save the selected options. When i save the option and reload the page the options are blank again.
And I was also wondering how to show the selected options on the single product page (frontend) as icon.
For now the function with the options works at the product variations. Please see this screenshot (product variation with multi select options):
My code:
// Add Variation Settings
add_action( 'woocommerce_product_after_variable_attributes', 'variation_settings_fields', 10, 3 );
/**
* Create custom field type
*
*/
function woocommerce_wp_select_multiple( $field ) {
global $thepostid, $post, $woocommerce;
$thepostid = empty( $thepostid ) ? $post->ID : $thepostid;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$field['value'] = isset( $field['value'] ) ? $field['value'] : ( get_post_meta( $thepostid, $field['id'], true ) ? get_post_meta( $thepostid, $field['id'], true ) : array() );
echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="' . esc_attr( $field['class'] ) . '" multiple="multiple">';
foreach ( $field['options'] as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . ( in_array( $key, $field['value'] ) ? 'selected="selected"' : '' ) . '>' . esc_html( $value ) . '</option>';
}
echo '</select> ';
if ( ! empty( $field['description'] ) ) {
if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
echo '<img class="help_tip" data-tip="' . esc_attr( $field['description'] ) . '" src="' . esc_url( WC()->plugin_url() ) . '/assets/images/help.png" height="16" width="16" />';
} else {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
}
echo '</p>';
}
/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {
woocommerce_wp_select_multiple( array(
'id' => 'season_' . $variation->ID,
'class' => 'season',
'label' => __('Season', 'woocommerce'),
'value' => get_post_meta( $variation->ID, '_season', true ),
'options' => array(
'spring' => 'Spring',
'summer' => 'Summer',
'autumn' => 'Autumn',
'winter' => 'Winter',
))
);
}
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $post_id ) {
$select = $_POST["season_$post_id"];
if( ! empty( $select ) ) {
update_post_meta( $post_id, '_season', esc_attr( $select ) );
}
}
To handle variable products for multi select fields is another thing and some changes need to be done to make it work. I have made 2 answers after below:
The first one for product variations (for you)
The other one for all other product types
So the main function that enable multi-select fields in WooCommerce backend will be:
function woocommerce_wp_multi_select( $field, $variation_id = 0 ) {
global $thepostid, $post;
if( $variation_id == 0 )
$the_id = empty( $thepostid ) ? $post->ID : $thepostid;
else
$the_id = $variation_id;
$field['class'] = isset( $field['class'] ) ? $field['class'] : 'select short';
$field['wrapper_class'] = isset( $field['wrapper_class'] ) ? $field['wrapper_class'] : '';
$field['name'] = isset( $field['name'] ) ? $field['name'] : $field['id'];
$meta_data = maybe_unserialize( get_post_meta( $the_id, $field['id'], true ) );
$meta_data = $meta_data ? $meta_data : array() ;
$field['value'] = isset( $field['value'] ) ? $field['value'] : $meta_data;
echo '<p class="form-field ' . esc_attr( $field['id'] ) . '_field ' . esc_attr( $field['wrapper_class'] ) . '"><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" class="' . esc_attr( $field['class'] ) . '" multiple="multiple">';
foreach ( $field['options'] as $key => $value ) {
echo '<option value="' . esc_attr( $key ) . '" ' . ( in_array( $key, $field['value'] ) ? 'selected="selected"' : '' ) . '>' . esc_html( $value ) . '</option>';
}
echo '</select> ';
if ( ! empty( $field['description'] ) ) {
if ( isset( $field['desc_tip'] ) && false !== $field['desc_tip'] ) {
echo '<img class="help_tip" data-tip="' . esc_attr( $field['description'] ) . '" src="' . esc_url( WC()->plugin_url() ) . '/assets/images/help.png" height="16" width="16" />';
} else {
echo '<span class="description">' . wp_kses_post( $field['description'] ) . '</span>';
}
}
}
Code goes in function.php file of your active child theme (or active theme). This function, will handle now any type of products, including product variations.
Related: Multi checkbox fields in Woocommerce backend
1). For product variations (for you):
// Add custom multi-select fields in variation setting tab
add_action( 'woocommerce_product_after_variable_attributes', 'add_variation_settings_fields', 20, 3 );
function add_variation_settings_fields( $loop, $variation_data, $variation_post ) {
woocommerce_wp_multi_select( array(
'id' => '_season',
'name' => '_season['.$loop.'][]',
'class' => '',
'label' => __('Season', 'woocommerce'),
'options' => array(
'spring' => __("Spring", "woocommerce"),
'summer' => __("Summer", "woocommerce"),
'autumn' => __("Autumn", "woocommerce"),
'winter' => __("Winter", "woocommerce"),
)
), $variation_post->ID );
}
// Save custom multi-select fields for variations
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );
function save_variation_settings_fields( $variation_id, $i ) {
if( isset( $_POST['_season'][$i] ) ){
$post_data = $_POST['_season'][$i];
// Multi data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $variation_id, '_season', $sanitize_data );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
2). For all other product types (except product variations, where we hide that custom field):
// Add custom fields for product general option settings (hidding it for variable products)
add_action( 'woocommerce_product_options_general_product_data', 'add_custom_settings_fields', 20 );
function add_custom_settings_fields() {
global $post;
echo '<div class="options_group hide_if_variable"">'; // Hidding in variable products
woocommerce_wp_multi_select( array(
'id' => '_season',
'name' => '_season[]',
'class' => '',
'label' => __('Season', 'woocommerce'),
'options' => array(
'spring' => __("Spring", "woocommerce"),
'summer' => __("Summer", "woocommerce"),
'autumn' => __("Autumn", "woocommerce"),
'winter' => __("Winter", "woocommerce"),
)
) );
echo '</div>';
}
// Save custom multi-select fields to database when submitted in Backend (for all other product types)
add_action( 'woocommerce_process_product_meta', 'save_product_options_custom_fields', 30, 1 );
function save_product_options_custom_fields( $post_id ){
if( isset( $_POST['_season'] ) ){
$post_data = $_POST['_season'];
// Multi data sanitization
$sanitize_data = array();
if( is_array($post_data) && sizeof($post_data) > 0 ){
foreach( $post_data as $value ){
$sanitize_data[] = esc_attr( $value );
}
}
update_post_meta( $post_id, '_season', $sanitize_data );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Categories