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 ><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" 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 data-tip="' . esc_attr( $field['description'] ) . '"></span>';
} else {
echo '<span >' . 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" >
<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 ) );
}
CodePudding user response:
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 ><label for="' . esc_attr( $field['id'] ) . '">' . wp_kses_post( $field['label'] ) . '</label><select id="' . esc_attr( $field['id'] ) . '" name="' . esc_attr( $field['name'] ) . '" 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 data-tip="' . esc_attr( $field['description'] ) . '"></span>';
} else {
echo '<span >' . 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" >';
// 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