Skip to main content

Data Context and Dynamic Sources

Most Woo authoring issues come from using the right component in the wrong data context. Start with the prefix, then choose the component.

Product Data: item vs this

Product data is exposed under omewoo when the current post is a Woo product.

| Where you are | Use this prefix | Example | | --- | --- | | Product archive or product loop | {item.*} | {item.id}, {item.title}, {item.omewoo.price.text} | | Single product template | {this.*} | {this.id}, {this.title}, {this.omewoo.price.text} |

Use the same field names in both contexts. Only the prefix changes.

ProductProvider is the one component that receives the complete object directly: use {item.omewoo} inside a product loop and {this.omewoo} on a single product template. Do not rebuild a partial object for it.

Product archive card uses item
{#loop products as item}
Product title: {item.title}
Product price: {item.omewoo.price.text}
<OmeWooAddToCartForm product='{{"product_id":"{item.id}","product_type":"{item.omewoo.product.type}"}}'>
{#slot default}
<OmeWooAddToCartButton behavior='{{"mode":"counter","trigger":"form_submit"}}' />
{/slot}
</OmeWooAddToCartForm>
{/loop}
Single product template uses this
Product title: {this.title}
Product price: {this.omewoo.price.text}
<OmeWooAddToCartForm product='{{"product_id":"{this.id}","product_type":"{this.omewoo.product.type}"}}'>
{#slot default}
<OmeWooAddToCartButton behavior='{{"mode":"counter","trigger":"form_submit"}}' />
{/slot}
</OmeWooAddToCartForm>

Common Product Fields

ExpressionUse
{item.id} or {this.id}Product ID for AddToCartForm.product.product_id.
{item.omewoo.product.type} or {this.omewoo.product.type}Product type for AddToCartForm.product.product_type.
{item.omewoo.price.text} or {this.omewoo.price.text}Formatted price text.
{item.omewoo.media.image.url} or {this.omewoo.media.image.url}Main product image URL.
{item.omewoo.media.image.alt} or {this.omewoo.media.image.alt}Main product image alt text.
{item.omewoo.media.gallery} or {this.omewoo.media.gallery}Ordered base media collection for ProductMedia.media.
{item.omewoo.media.variationGalleries} or {this.omewoo.media.variationGalleries}Selector-aware variation galleries consumed through the nearest ProductProvider.
{item.omewoo.attributes} or {this.omewoo.attributes}Variable-product attributes for AttributeSelector.
{item.omewoo.variants} or {this.omewoo.variants}Variation catalogue for AddToCartForm variation resolution.

Keep gallery-aware UI and purchase UI on separate data paths. Bind omewoo.media.image.id to a hero ProductImage, omewoo.media.gallery to ProductMedia, and pass the complete omewoo object to the nearest ProductProvider so it can resolve media.variationGalleries. Continue using omewoo.variants only for AddToCartForm variation resolution.

See Woo Dynamic Data Tree for the full field-by-field reference.

Product Provider Scope

OmeWooProductProvider stores the base product and derived variable-product selection state for its nearest descendants. It is a real structural DOM container and supports only simple and variable products. Use structure.tag to choose the root tag and styling.class to control its layout and presentation.

<OmeWooProductProvider product="{this.omewoo}">
{#slot default}
<OmeWooAddToCartForm>...</OmeWooAddToCartForm>
{/slot}
</OmeWooProductProvider>

In a product loop, replace this with item and render one Provider per loop item. A nested Provider is an isolation boundary; descendants never read selection state from an outer Provider. The Provider exposes derived read-only state, while AttributeSelector, VariationResetButton, quantity, and cart mutation controls remain scoped to AddToCartForm.

ProductImage and ProductMedia also use the nearest Provider. Product Media selection changes the Provider's active image only; it does not change the current variation or submit anything. Both atoms preserve their authored server-rendered output when used without a valid Provider, with a development-only warning explaining how to enable synchronization.

Standalone AddToCartForm remains valid. It uses the same variation-selection controller internally and keeps its released DOM and submit contracts.

Variation Post Context

When the queried post is Woo's native product_variation, omewoo describes that variation. Its media.gallery describes the current variation, while media.variationGalleries, attributes, and variants stay empty because selector maps belong to the parent variable product. Variation templates should use parentProduct for parent identity and selectedAttributes for displayable selected values.

ExpressionUse
{this.omewoo.parentProduct}Parent product identity when the current post is a Woo variation.
{this.omewoo.selectedAttributes}Displayable selected variation attributes.
{this.omewoo.selectedAttributesMap}Normalized selected variation values keyed by Store API attribute key.

Cart Dynamic Sources

CartItemsDynamicSource registers four source keys when the block tree contains cart-aware components or expressions:

SourceShape
cartItemsCart item rows with key, compatibility productId, additive exact purchasableId, title fields, attributes, quantity, additive quantityLimits, URL, price text, subtotal text, and image data.
cartSummaryitem_count, line_count, and state where state is has-items or empty.
cartTotalsReleased flat total fields plus the additive cartAmount lane for tax-aware shopper measures, nullable shipping state, and currency metadata.
cartCouponsApplied coupon rows with code.

The source registration is lazy. A page that does not render cart components does not register cart sources for that request.

For new total readouts, use OmeWooCartAmount. Its server-rendered source at cartTotals.cartAmount mirrors Store API minor-unit totals: split total_items/total_items_tax, total_discount/total_discount_tax, total_fees/total_fees_tax, nullable total_shipping/total_shipping_tax, direct total_tax, direct total_price, shipping calculation flags, normalized tax display, and currency metadata. The component keeps this server-rendered output until the Cart Store confirms hydration.

The existing flat cartTotals fields remain unchanged for the five released fixed total atoms. Those compatibility fields can expose a positive discount and missing-value-to-zero behavior, so they are not silently migrated into the shopper-tax-aware lane. See Cart Totals for the component choice and exact state rules.

Cart Item Hydration

CartItems renders one authored row template. Server render and runtime both hydrate the row's atoms:

Atom markerData field
data-ome-woo-cart-item-field="image"Product image URL, srcset, and alt text with authored fallback.
data-ome-woo-cart-item-field="title"Product title or composed variant title.
data-ome-woo-cart-item-field="priceText"Unit price text.
data-ome-woo-cart-item-field="subtotalText"Line subtotal text.
data-ome-woo-cart-item-quantityCanonical quantity input value, exact cart item key, and Woo quantity limits.
data-ome-woo-cart-item-quantity-stepperOpt-in decrease/value/increase presentation backed by the canonical exact-line input.
data-ome-woo-cart-item-removeRemove button cart item key.
data-ome-woo-cart-attribute-listSelected variation attributes cloned from the attribute template.

This is why cart item atoms are meaningful only inside a cart item row or an order summary row.

productId keeps its released compatibility semantics unchanged. purchasableId is the explicit exact identity used for product-level cart matching: the variation ID for a variation line, otherwise the simple product ID. Existing consumers do not need to migrate, and standard lines may expose the same value in both fields. ProductCartQuantity uses the additive field conservatively and disables mutation when more than one line matches; it does not infer plugin-defined bundle, composite, add-on, or custom line identity.

Selector Sources

WooSelectorDynamicSource registers selector rows while blocks render:

SourceUsed by
shippingRatesShippingMethodSelector rows.
paymentMethodsPaymentMethodSelector rows and runtime config.

Shipping rates use package-aware values. The row value is {package_id}:{rate_id}, while the hidden input keeps the raw Woo rate ID and package-specific input name. This lets Woo distinguish rates across packages.

Payment methods only include enabled simple gateways. Gateways with custom fields are skipped by get_simple_payment_methods(), because this selector renders simple radio/select choices rather than gateway-specific embedded forms.

Checkout Field Schema

CheckoutFieldSchema::build() reads Woo countries, checkout fields, locale overrides, states, and store defaults. The runtime uses that schema to:

  • Render country options.
  • Switch state between select, text, and hidden modes.
  • Apply Woo labels, required flags, hidden flags, field types, autocomplete, and priorities.
  • Validate rendered fields before Store API submit.

Address forms still expose copy props, but use_woo_defaults: true keeps Woo's field copy as the default source.

Dynamic Data Examples

Variable selector loop on a single product:

{#loop this.omewoo.attributes as attribute}
<OmeWooAttributeSelector target='{{"attribute":{attribute}}}' />
{/loop}

The same selector loop inside a product archive card uses item:

{#loop item.omewoo.attributes as attribute}
<OmeWooAttributeSelector target='{{"attribute":{attribute}}}' />
{/loop}