Developer forum

Forum » Swift » variant change not triggering complete page reload

variant change not triggering complete page reload

Christoffer Rosendahl Frede
Reply

Hi everyone.

i discovered a kind of odd issue. i am testing on Dynamicweb version 10.23.1 and using Swift version v2.1.0

when i change the variant on a productpage it seems like it does not get completely reloaded. when i inspect the document, it looks like javascript

replaces the <main></main> content with the new variant data. but the entire <head></head> element stays the same. does anyone know if that is working as intended ?

or is there some Ecom settings or other settings, that can change this behaviour ?

/best regards Christoffer

 


Replies

 
Nicolai Pedersen Dynamicweb Employee
Nicolai Pedersen
Reply

It is intended - as we designed to make the UX flow fine.

When you do it, the page content changes fast and interactively - but the header section does not. The URL does change - and if you reload the page, the header section is for the variant as well. 

Our JS fires events - you should be able to overrule how we navigate - below untested version of how that can be done.
 

There is an interception point: selectioncomplete.swift.variantselector is fired before the URL update + PageUpdater.Update(...) fetch happens, and it’s cancelable (our code checks dispatchEvent(...) != false). So you can create a script that calls preventDefault() and do a full navigation instead.

Option A (best): cancel the async swap and do a real page load to the selected variant

Drop this on the product page (after Swift scripts are loaded):

<script>
(function () {
  function buildVariantUrl(variantSelectorEl, selections) {
    // Mirror Swift logic: base-url OR current URL with variantid param
    var variantid = selections.join(".");
    var baseUrl = variantSelectorEl.getAttribute("data-base-url");

    if (baseUrl) {
      // baseUrl is already a full URL (often includes querystring)
      return baseUrl + "&variantid=" + encodeURIComponent(variantid);
    }

    var url = new URL(window.location.href);
    url.searchParams.set("variantid", variantid);
    return url.toString();
  }

  // Attach locally to each selector so we can access e.target reliably
  document.querySelectorAll(".js-variant-selector").forEach(function (vs) {
    vs.addEventListener("selectioncomplete.swift.variantselector", function (e) {
      // Stop Swift from calling PageUpdater.Update(...)
      e.preventDefault();

      var url = buildVariantUrl(vs, e.detail && e.detail.selections ? e.detail.selections : []);

      // Full reload (updates <head>, canonical, meta, structured data, etc.)
      window.location.href = url;
    });
  });
})();
</script>

How this works:

  • selectioncomplete.swift.variantselector is dispatched before window.history.replaceState(...) and before PageUpdater.Update(variantSelectorElement) is called.

  • Because it’s cancelable: true, e.preventDefault() makes dispatchEvent(...) return false, and your code short-circuits the inline update.

Option B (fallback): let it swap inline, then immediately reload the page

This is the “brute force” version: it allows the fetch + DOM swap, then reloads. It’s less efficient (double work), but sometimes partners prefer “no logic, just reload”.

<script>
(function () {
  // Fires after fetch completed and HTML is available (but before swap decision completes)
  document.addEventListener("updated.swift.pageupdater", function () {
    window.location.reload();
  }, { once: true });
})();
</script>

Notes:

  • updated.swift.pageupdater is fired after the fetch returns HTML (response.text()), right before/around the replacement path.

  • If you want to reload after the DOM has been replaced, hook swapped.swift.pageupdater instead (it’s dispatched after innerHTML = html in Success).

Tiny gotcha worth calling out

If you use Option B, make it { once: true } (as above) or you can get reload loops if other parts of the page also trigger page updates.

 

You must be logged in to post in the forum