Automatically closed - issue fixed for 2 weeks with no activity.
- Status changed to Fixed
2 months ago 11:27pm 6 February 2025 - πΊπΈUnited States dbroll
FYI for anyone trying to do this in D10 I copied the existing field formatter and added some logic to remove the price if it's 0.
Then you must enable the new formatter in: Commerce > Config > Shipping > Shipment Types > Manage form display (checkout)
src/Plugin/Field/FieldWidget/YOUR_MODULEShippingRateWidget.php
<?php namespace Drupal\YOUR_MODULE\Plugin\Field\FieldWidget; use Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowWithPanesInterface; use Drupal\commerce_shipping\Plugin\Field\FieldWidget\ShippingRateWidget; use Drupal\Component\Render\FormattableMarkup; use Drupal\Component\Utility\NestedArray; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Form\FormStateInterface; /** * Plugin implementation of the 'commerce_shipping_rate' widget. * * @FieldWidget( * id = "your_module_shipping_rate", * label = @Translation("YOUR_MODULE Shipping Rate (0 removal)"), * field_types = { * "entity_reference" * } * ) */ class YOUR_MODULEShippingRateWidget extends ShippingRateWidget { /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { /** @var \Drupal\commerce_shipping\Entity\ShipmentInterface $shipment */ $shipment = $items[$delta]->getEntity(); $parents = array_merge($form['#parents'], [$this->fieldDefinition->getName(), 0]); $rates_key = implode('_', $parents); // Store the calculated rates in form state to avoid repeated calculations. if (!$form_state->has($rates_key) || $form_state->get('recalculate_shipping')) { $form_state->set($rates_key, $this->shipmentManager->calculateRates($shipment)); } $rates = $form_state->get($rates_key); if (!$rates) { // When there are no rates available for this address, clear the selected rate. $shipment->clearRate(); $element = [ '#markup' => $this->t('There are no shipping rates available for this address.'), ]; return $element; } $default_rate = $this->shipmentManager->selectDefaultRate($shipment, $rates); // If we're in checkout, attach an AJAX callback to refresh the order summary. if ($form_state->getFormObject() instanceof CheckoutFlowWithPanesInterface) { $element['#ajax'] = [ 'callback' => [get_called_class(), 'ajaxRefreshForm'], ]; $parents = array_merge($form['#parents'], [$this->fieldDefinition->getName(), 0]); $user_input = (array) NestedArray::getValue($form_state->getUserInput(), $parents); // Apply the default rate if no rate is selected. if (empty($user_input)) { $this->shipmentManager->applyRate($shipment, $default_rate); } } $element['#type'] = 'radios'; $element['#default_value'] = $default_rate->getId(); $element['#options'] = []; foreach ($rates as $rate_id => $rate) { $amount = $rate->getAmount(); $pre_promotion_amount = $rate->getPrePromotionAmount(); // If the shipping amount is 0.00, display only the service label. if (floatval($amount->getNumber()) == 0) { $rate_label = new FormattableMarkup('@service', [ '@service' => $rate->getService()->getLabel(), ]); } else { if ($pre_promotion_amount && $pre_promotion_amount->greaterThan($amount)) { $rate_label = new FormattableMarkup('@service: <s>@original_amount</s> @amount', [ '@service' => $rate->getService()->getLabel(), '@original_amount' => $this->currencyFormatter->format($pre_promotion_amount->getNumber(), $pre_promotion_amount->getCurrencyCode()), '@amount' => $this->currencyFormatter->format($amount->getNumber(), $amount->getCurrencyCode()), ]); } else { $rate_label = new FormattableMarkup('@service: @amount', [ '@service' => $rate->getService()->getLabel(), '@amount' => $this->currencyFormatter->format($amount->getNumber(), $amount->getCurrencyCode()), ]); } } $element['#options'][$rate_id] = $rate_label; $element[$rate_id]['#description'] = $rate->getDescription(); // Prevent Bootstrap (if used) from converting the description into a tooltip. $element[$rate_id]['#smart_description'] = FALSE; // Store the rate object for use in extractFormValues(). $element[$rate_id]['#rate'] = $rate; } return $element; } }