Skip to content

fix(ep-commerce): the EP Catalog Search insert template is not wired to real data or real interactions #457

Description

@field123

Inserting EP Catalog Search Provider composes a template of EP Search Box → EP Search Hits → EP Search Pagination. It looks wired but the leaves are literal text, so every product card reads the same regardless of data:

component ships as its slot default
EPSearchHits "Product Name", "$0.00" — one identical card per hit
EPSearchPagination "Prev", "Page 1 of 4", "Next" — an invented page count
EPSearchAutocompleteList "Suggestion"

The runtime path is fine: the provider fetches real hits and #301 wired EPSearchHits to resolved main_image. EPSearchHits publishes currentProduct, currentHit and currentProductIndex per hit. The default slot content simply binds to none of it. {repeatedElement(i, children)} also has no fallback, so emptying the slot renders nothing rather than something real.

This is the defect class #447 and #448 addressed — defaults that show fake money — in two components that were outside that review's scope.

Why it shipped this way, and what changed

#311 shipped the pagination default deliberately unbound: "The skeleton ships unbound (same constraint that blocked EPSearchBox from shipping bindings in defaultValue)." Same for EPSearchBox in #308. Under that constraint, a structural-but-fake skeleton was the best available option.

That constraint no longer decides the outcome. #448 established a code-rendered default pattern across five components — DefaultRefinementChip, DefaultRateRow, the default totals rows, and the checkout button's step-aware label — where the component renders real context data itself when the slot is empty. A slot default is not the only way to give a designer something on insert.

Fix

For each component: drop the static defaultValue, add hidePlaceholder: true, and render a code-level default from the data the component already provides.

  • EPSearchHits — a DefaultHitCard using currentProduct's image, name and useMoneyFormat-formatted price.
  • EPSearchPagination — Prev / page indicator / Next driven by searchPaginationData (currentPage, totalPages, hasPrev, hasNext), with the existing ref actions wired, matching how DefaultRateRow handles its own selection.
  • EPSearchAutocompleteList — the real suggestion text. Lower priority.

Existing instances keep whatever slot content they were authored with; only fresh inserts change.

Worth knowing when implementing: a designer who fills a slot and then clears it gets [], which is truthy and non-nullish, so both children ?? default and children ? … : default render nothing. Consistent with the rest of the package, but it means "I emptied the slot" and "I never touched the slot" behave differently.

Related

Found reviewing the inserted template in integration Studio against the published 0.4.0 components.


The template's search box does nothing either

Typing in the inserted EP Search Box has no effect on the hits. Its slot default ships a real <input type="search" placeholder="Search products..."> and a Clear button, but neither is connected: the component expects the designer to bind them to $ctx.searchFieldData and the setValue / clear ref actions, per its own description.

That is the same deliberate choice as #308, and the same constraint. What makes it a defect rather than a design decision is that three siblings already do the opposite via Pattern C (cloneWithInjectedHandlers, #315): EPCurrentRefinements, EPClearRefinements, and EPSearchAutocompleteInput — which injects value, onChange, onKeyDown, onFocus and onBlur into its own slotted <input type="search">.

So the autocomplete search input works on insert and the plain search box does not, for the same interaction in the same package.

EPSearchBox should adopt Pattern C: inject value and onChange into the slotted input (debounced through the existing scheduleRefine) and onClick into the clear button, keeping the single-element-slot fallback EPSearchAutocompleteInput already uses for designers who drop something unexpected. cloneWithInjectedHandlers exists and is covered by cloneWithInjectedHandlers.test.tsx.

This is the most severe item here: fake prices are misleading, but a search page whose search field does nothing is not usable at all without wiring nobody is told about at insert time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions