NO BUG: 2.4-beta: only the first "Checkout order summary" is refreshed by update_order_review — a second instance (mobile/desktop layout) goes stale

Bricks version: 2.4-beta

Symptom: A checkout built the common way — one order summary inside a collapsible panel for small screens, another in the sticky right column for large ones, each shown by a breakpoint — updates only one of them. Whichever instance is second in the DOM keeps whatever it rendered at page load. Applying a coupon appears to do nothing until the page is reloaded.

It is not specific to coupons: the same fragment carries every updated_checkout, so choosing a shipping method, entering an address that changes the tax, or editing a quantity also leaves the visible summary showing a total the customer will not be charged. On mobile that is the only summary they see.

Root cause: the element is a singleton at both ends.

  1. includes/woocommerce/elements/woocommerce-checkout-order-summary.php forces a fixed root id on every instance:
$this->set_attribute( '_root', 'id', 'bricks-woo-checkout-order-summary' );

$this->attributes['_root']['id'] = 'bricks-woo-checkout-order-summary';

so two summaries produce two elements with the same id (also invalid HTML).

  1. includes/woocommerce.php::update_order_review_fragments() stops at the first matching element (is_null( $checkout_order_root )) and registers the fragment under that id:
$fragments['#bricks-woo-checkout-order-summary'] = \Bricks\Frontend::render_data( $checkout_order_summary_elements );

WooCommerce’s checkout.js then runs $( key ).replaceWith( value ). jQuery resolves a bare #id through getElementById, so exactly one node is replaced regardless of how many share the id.

Note on the obvious fix: switching to a class selector — the way the neighbouring fragments in the same method already do for .brxe-woocommerce-shipping-options and .brxe-woocommerce-payment-options — is not enough here. Those instances share one markup blob, whereas two summaries are two different subtrees whose styling is keyed on their own .brxe-{id}. Replacing both with one rendered blob would give one instance the other’s markup and styling. The fragment has to be produced per instance.

Fix suggestion: drop the forced shared id, keep each instance addressable by something unique (its own .brxe-{id} is already there), and in update_order_review_fragments() loop over every woocommerce-checkout-order-summary element instead of breaking at the first, emitting one fragment per instance.

Workaround we’re using: a filter on woocommerce_update_order_review_fragments at priority 20 that stamps each instance with a class derived from its Bricks element id (via bricks/element/render_attributes), renders each subtree with \Bricks\Woocommerce::extract_element_data_from_root() + \Bricks\Frontend::render_data(), emits one fragment per instance and unsets the native #bricks-woo-checkout-order-summary key. Confirmed working on 375px and 1280px across repeated apply/remove cycles.

Hi @byGracjan ,

Thanks for the detailed report. Checkout v2 supports one Checkout order summary wrapper per checkout state, matching WooCommerce’s single order-review region. Duplicating this wrapper for separate desktop and mobile positions creates duplicate fragment targets and is not supported.

Please keep one order summary instance and reposition or reflow it responsively using the layout and breakpoint controls.

Regards,
Jenn