- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在我的项目中,我正在自定义一些 WooCommerce 功能。
我的“运送方式”是:
1.发货
2.带走
我还在结账页面添加了一个自定义字段,即 <select>
填充有效的送货时间(情况“1”)或外卖时间(情况“2”)。
用户可能会选择 2. take away
在购物车页面中,然后选择对“2”有效的时间,但随后更改为 1. delivery
并且所选时间可能不再有效,选项列表和自定义字段标签也不再有效。
当然,我正在使用 woocommerce_checkout_process
通过 wc_add_notice()
警告用户的钩子(Hook),但即使woocommerce_checkout_fields
钩子(Hook)被触发(这就是我创建选择列表的地方),<select>
值未更新。
我认为有一个 AJAX 调用仅与运输方式相关,并且不会更新其他结帐字段,尽管 woocommerce_checkout_fields
钩子(Hook)被触发。
如何更新自定义字段?我需要一些 js/jquery/AJAX 吗?
或者:自定义字段是否可以与运输方式相关(并通过 AJAX 进行更新)?怎么办?
编辑
自定义字段代码:
add_filter( 'woocommerce_checkout_fields', 'fty_filter_checkout_fields' );
function my_filter_checkout_fields($fields) {
$must_deliver = WC()->cart->shipping_total > 0.0; // true=deliver, false=take away
// some complex code to calculate time lists omitted, samples array instead:
$delivery_time_list = array(
"deliver 10:00",
"deliver 11:00",
"deliver 12:00",
"deliver 13:00"
);
$takeaway_time_list = array(
"takeaway 10:00",
"takeaway 10:30",
"takeaway 11:00",
"takeaway 11:30",
"takeaway 12:00",
"takeaway 12:30",
"takeaway 13:00",
"takeaway 13:30"
);
// add the new conditional field
if($must_deliver) {
$fields['my_delivery_datetime'] = array(
'my_delivery_time' => array(
'type' => 'select',
'options' => $delivery_time_list,
'required' => true,
'label' => __('Delivery time')
)
);
} else {
$fields['my_delivery_time'] = array(
'my_delivery_time' => array(
'type' => 'select',
'options' => $takeaway_time_list,
'required' => true,
'label' => __('Take away time')
)
);
}
return $fields;
}
验证代码的想法:
add_action('woocommerce_checkout_process', 'my_checkout_date_time_validation', 30, 1);
function my_checkout_date_time_validation($doh) {
$time = filter_input(INPUT_POST, 'my_delivery_time');
$shipping = filter_input(INPUT_POST, 'shipping_method', FILTER_DEFAULT, FILTER_REQUIRE_ARRAY);
if(strpos($time, "deliver")!==FALSE && strpos($shipping[0], "local_pickup")!==FALSE) {
wc_add_notice('Please re-select take away time', 'error');
} else if(strpos($time, "takeaway")!==FALSE && strpos($shipping[0], "distance_based_rate")!==FALSE) {
wc_add_notice('Please re-select delivery time', 'error');
}
}
这是关于运输方式的信息;
add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_distance_based_delivery_rate', 10, 2 );
function add_distance_based_delivery_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['id'] .= ':' . 'distance_based_rate';
$new_rate['label'] = 'delivery'; // Rename to 'Rushed Shipping'.
// incredibly complex code used to calculate delivery costs omitted
$dist_cost = 1000;
$new_rate['cost'] += $dist_cost;
$method->add_rate( $new_rate );
}
谢谢!
最佳答案
提供的代码大多没有用......我做了很多更改和优化。我的所有代码都带有注释,在 WooCommerce 3+ 上进行了测试并且完美运行。
<小时/>You will have to add your "incredibly complex code used to calculate delivery costs omitted"…
1) 用于条件结帐字段现场事件的 JavaScript
参与客户现场事件(浏览器端)的唯一方法是 javascript/jQuery。所以这并不容易,因为 WooCommerce 在结账页面上已经使用了大量的 javascript/jQuery/Ajax...
我已将 javascript 代码包含到 Hook 函数中,但您应该将其保存在单独的文件中,并使用经典的 WordPress 注册脚本函数注册此脚本文件,如以下线程所示:
Checkout fields: Hiding and showing existing fields
2) 使用现有的运输方式(动态价格计算):
您无需创建任何运费。您可以使用:
对于您的每个送货区域,在 Woocommerce > 设置 > 送货中启用、设置和重命名(标签名称) 2 种方法:
对于统一费率,您可以设置任何最低金额(该金额将被您的计算覆盖)...
If you make changes you need to refresh shipping cached data: disable, save and enable, save those methods for the current shipping zone.
3) 节省订购元数据的运输时间:
我为此添加了一些代码,并将其保存在 2 个自定义元字段中:
4) 在元框中显示所选的运输类型和时间(在订单编辑页面中):
我还为此添加了一些代码。
最后是代码:
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
// The 2 Options arrays in imput select
$delivery_time_list[''] = $takeaway_time_list[''] = __('Select an hour');
for($h = 10, $i = 0; $i < 8; $i++ ){
if( $i % 2 == 0 ){
$time = $h.':00';
$delivery_time_list[$time] = 'deliver '.$time;
} else {
$time = $h.':30';
$h++;
}
$takeaway_time_list[$time] = 'takeaway '.$time;
}
echo '<div id="delivery_checkout_fields"><h3>' . __('Shipping time options') . '</h3>';
woocommerce_form_field( 'delivery_time', array(
'type' => 'select',
'class' => array('delivery-time form-row-wide'),
'label' => __('Delivery time'),
'options' => $delivery_time_list,
), $checkout->get_value( 'delivery_time' ) );
woocommerce_form_field( 'takeaway_time', array(
'type' => 'select',
'class' => array('takeaway-time form-row-wide'),
'label' => __('Take away time'),
'options' => $takeaway_time_list,
), $checkout->get_value( 'takeaway_time' ) );
echo '</div>';
$required = esc_attr__( 'required', 'woocommerce' );
?>
<script>
jQuery(function($){
var choosenShipMethod = $('input[name^="shipping_method"]:checked').val().split(':')[0], // Choosen shipping method slug
required = '<abbr class="required" title="<?php echo $required; ?>">*</abbr>'; // Required html
// TESTING: displaying in console the choosen shipping
console.log('Chosen shipping: '+choosenShipMethod);
// Function that shows or hide imput select fields
function showHide( actionToDo='show', selector='' ){
if( actionToDo == 'show' )
$(selector).show(function(){
$(this).addClass("validate-required");
$(this).removeClass("woocommerce-validated");
$(this).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
$(selector+' label').append(required);
//console.log('Selector (show): '+selector);
});
else
$(selector).hide(function(){
$(this).removeClass("validate-required");
$(this).removeClass("woocommerce-validated");
$(this).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
$(selector+' label > .required').remove();
//console.log('Selector (hide): '+selector);
});
}
// Initialising at start (Based on the choosen shipping method)
if( choosenShipMethod == 'flat_rate' ) // Choosen "Delivery" (Hidding "Take away")
{
showHide('show','#delivery_time_field' );
showHide('hide','#takeaway_time_field' );
}
else if( choosenShipMethod == 'local_pickup' ) // Choosen "Take away" (Hidding "Delivery")
{
showHide('show','#takeaway_time_field' );
showHide('hide','#delivery_time_field' );
}
else // No shipping choosen yet (Hidding BOTH shipping dropdown hour selectors
{
showHide('hide','#delivery_time_field' );
showHide('hide','#takeaway_time_field' );
$('#delivery_checkout_fields').hide();
}
// When shipping method is changed (Live event)
$( 'form.checkout' ).on( 'change', 'input[name^="shipping_method"]', function() {
var changedShipMethod = $('input[name^="shipping_method"]:checked').val().split(':')[0];
if( changedShipMethod == 'flat_rate' )
{
// Choose "Delivery" | Show "Delivery" and Hide "Take away"
$('#delivery_checkout_fields').show();
showHide('show','#delivery_time_field' );
showHide('hide','#takeaway_time_field' );
}
else if( changedShipMethod == 'local_pickup' )
{
// Choose "Take away" | Show "Take away" and Hide "Delivery"
$('#delivery_checkout_fields').show();
showHide('show','#takeaway_time_field' );
showHide('hide','#delivery_time_field' );
}
console.log("Chosen shipping: "+changedShipMethod);
});
// When an hour is selected (LIVE event)
$('#delivery_checkout_fields select').change( function(){
if( $(this).val() != '')
$(this).parent().removeClass("validate-required");
else
$(this).parent().addClass("validate-required");
console.log("Selector value: "+$(this).val());
});
// "select.shipping_method, input[name^="shipping_method"], #ship-to-different-address input, .update_totals_on_change select, .update_totals_on_change input[type="radio"], .update_totals_on_change input[type="checkbox"]"
//"function (){t.reset_update_checkout_timer(),t.dirtyInput=!1,e(document.body).trigger("update_checkout")}"
});
</script>
<?php
}
// Process the checkout (Checking if required fields are not empty)
add_action('woocommerce_checkout_process', 'ba_custom_checkout_field_process');
function ba_custom_checkout_field_process() {
$delivery_time = $takeaway_time = 0;
if ( $_POST['delivery_time'] ) $delivery_time = 1;
if ( $_POST['takeaway_time'] ) $takeaway_time = 1;
// Only one message is possible for both
if ( ( $delivery_time + $takeaway_time ) == 0 ){
wc_add_notice( __('Please select a <strong>shipping time</strong>.' ), 'error');
}
}
## CALCULATING THE DELIVERY FEE (BASED ON COUNTING THE DIFFERENT DATES For all items) ##
add_filter( 'woocommerce_package_rates', 'custom_shipping_flat_rate_cost_calculation', 10, 2 );
function custom_shipping_flat_rate_cost_calculation( $rates, $package )
{
## --- CALCULATIONS Based on CART DATA (if needed) --- ##
foreach(WC()->cart->get_cart() as $cart_item ):
// HERE your incredibly complex code used to calculate delivery costs
endforeach;
## --- CHANGING DYNAMICALLY THE METHODS COSTS --- ##
foreach($rates as $rate_key => $rate_values):
$method_id = $rate_values->method_id;
$rate_id = $rate_values->id;
// "DELIVERY" - "local_pickup" method (if needed)
if ( 'flat_rate' === $method_id ){
// HERE your incredibly complex code used to calculate delivery costs
// Change the price cost
$price_excl_tax = $rates[$rate_id]->cost + 2.5;
$rates[$rate_id]->cost = number_format($price_excl_tax, 2);
$tax_calculation = $rates[$rate_id]->taxes[0] * 0.1;
$rates[$rate_id]->taxes[0] = number_format($tax_calculation, 2);
}
// "TAKE WAY" - "local_pickup" method (if needed)
elseif ( 'local_pickup' === $method_id )
{
// do something if needed
}
endforeach;
return $rates;
}
// Save the "shipping time" in order meta data
add_action( 'woocommerce_checkout_update_order_meta', 'save_shipping_time_in_order_meta', 100, 1 );
function save_shipping_time_in_order_meta( $order_id ) {
// Take away time
$takeaway_time = $_POST['takeaway_time'];
if ( ! empty( $takeaway_time ) ){
add_post_meta( $order_id, '_shipping_time', $takeaway_time );
add_post_meta( $order_id, '_shipping_type', __('Take away', 'woocommerce' ) );
}
// Delivery time
$delivery_time = $_POST['delivery_time'];
if ( ! empty( $delivery_time ) ){
add_post_meta( $order_id, '_shipping_time', $delivery_time );
add_post_meta( $order_id, '_shipping_type', __('Delivery', 'woocommerce' ) );
}
}
// Adding shipping time metabox (on right side) to Order edit pages
add_action( 'add_meta_boxes', 'add_order_shipping_time_meta_boxe' );
function add_order_shipping_time_meta_boxe(){
add_meta_box(
'woocommerce-order-shipping-time-values', __( 'Shipping type and time', 'woocommerce' ),
'order_shipping_time_values', 'shop_order', 'side', 'default'
);
}
// Adding content to shipping time metabox to Order edit pages
function order_shipping_time_values(){
global $post;
$type = get_post_meta($post->ID, '_shipping_type', true);
$time = get_post_meta($post->ID, '_shipping_time', true);
echo "<p><strong>Type:</strong> $type | <strong>time:</strong> $time</p>";
}
代码位于事件子主题(或主题)的 function.php 文件中或任何插件文件中。
此代码在 WooCommerce 3+ 上经过测试并且有效。
关于php - WooCommerce:结帐验证失败后更新自定义字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45243303/
好的,所以我编辑了以下... 只需将以下内容放入我的 custom.css #rt-utility .rt-block {CODE HERE} 但是当我尝试改变... 与 #rt-sideslid
在表格 View 中,我有一个自定义单元格(在界面生成器中高度为 500)。在该单元格中,我有一个 Collection View ,我按 (10,10,10,10) 固定到边缘。但是在 tablev
对于我的无能,我很抱歉,但总的来说,我对 Cocoa、Swift 和面向对象编程还很陌生。我的主要来源是《Cocoa Programming for OS X》(第 5 版),以及 Apple 的充满
我正在使用 meta-tegra 为我的 NVIDIA Jetson Nano 构建自定义图像。我需要 PyTorch,但没有它的配方。我在设备上构建了 PyTorch,并将其打包到设备上的轮子中。现
在 jquery 中使用 $.POST 和 $.GET 时,有没有办法将自定义变量添加到 URL 并发送它们?我尝试了以下方法: $.ajax({type:"POST", url:"file.php?
Traefik 已经默认实现了很多中间件,可以满足大部分我们日常的需求,但是在实际工作中,用户仍然还是有自定义中间件的需求,为解决这个问题,官方推出了一个 Traefik Pilot[1] 的功
我想让我的 CustomTextInputLayout 将 Widget.MaterialComponents.TextInputLayout.OutlinedBox 作为默认样式,无需在 XML 中
我在 ~/.emacs 中有以下自定义函数: (defun xi-rgrep (term) (grep-compute-defaults) (interactive "sSearch Te
我有下表: 考虑到每个月的权重,我的目标是在 5 个月内分散 10,000 个单位。与 10,000 相邻的行是我最好的尝试(我在这上面花了几个小时)。黄色是我所追求的。 我试图用来计算的逻辑如下:计
我的表单中有一个字段,它是文件类型。当用户点击保存图标时,我想自然地将文件上传到服务器并将文件名保存在数据库中。我尝试通过回显文件名来测试它,但它似乎不起作用。另外,如何将文件名添加到数据库中?是在模
我有一个 python 脚本来发送电子邮件,它工作得很好,但问题是当我检查我的电子邮件收件箱时。 我希望该用户名是自定义用户名,而不是整个电子邮件地址。 最佳答案 发件人地址应该使用的格式是: You
我想减小 ggcorrplot 中标记的大小,并减少文本和绘图之间的空间。 library(ggcorrplot) data(mtcars) corr <- round(cor(mtcars), 1)
GTK+ noob 问题在这里: 是否可以自定义 GtkFileChooserButton 或 GtkFileChooserDialog 以删除“位置”部分(左侧)和顶部的“位置”输入框? 我实际上要
我正在尝试在主页上使用 ajax 在 magento 中使用 ajax 显示流行的产品列表,我可以为 5 或“N”个产品执行此操作,但我想要的是将分页工具栏与结果集一起添加. 这是我添加的以显示流行产
我正在尝试使用 PasswordResetForm 内置函数。 由于我想要自定义表单字段,因此我编写了自己的表单: class FpasswordForm(PasswordResetForm):
据我了解,新的 Angular 7 提供了拖放功能。我搜索了有关 DnD 的 Tree 组件,但没有找到与树相关的内容。 我在 Stackblitz 上找到的一个工作示例.对比drag'ndrop功能
我必须开发一个自定义选项卡控件并决定使用 WPF/XAML 创建它,因为我无论如何都打算学习它。完成后应该是这样的: 到目前为止,我取得了很好的进展,但还有两个问题: 只有第一个/最后一个标签项应该有
我要定制xtable用于导出到 LaTeX。我知道有些问题是关于 xtable在这里,但我找不到我要找的具体东西。 以下是我的表的外观示例: my.table <- data.frame(Specif
用ejs在这里显示日期 它给我结果 Tue Feb 02 2016 16:02:24 GMT+0530 (IST) 但是我需要表现为 19th January, 2016 如何在ejs中执行此操作?
我想问在 JavaFX 中使用自定义对象制作 ListView 的最佳方法,我想要一个每个项目如下所示的列表: 我搜了一下,发现大部分人都是用细胞工厂的方法来做的。有没有其他办法?例如使用客户 fxm
我是一名优秀的程序员,十分优秀!