Welcome @Proporus – this is not directly related to LiveView. In fact, there is currently an open issue for the HTML spec: whether to add a new mode for iframes where they don’t add to the joint session history.
Is there a way to avoid this?
Yes, I found two different methods to solve this problem and both will use a small client-side Javascript hook.
The wrapper div received a phx-hook and therefore it also received a required id.
The buttons lost their phx-click attribute.
Although not strictly necessary, for clarity the src attribute changed from phx-value-src to data-src.
Next, let’s setup IframeSwitch:
let IframeSwitch = {
buttons() { return Array.from(this.el.querySelectorAll("button")); },
iframe() { return this.el.querySelector("iframe"); },
mounted() {
this.buttons().forEach(btn => {
btn.addEventListener("click", (e) => {
// Invoke location.replace(src) on the iframe's window.
// This approach will not update the joint session history,
// however, it may not work for all sources.
//
this.iframe().contentWindow.location.replace(e.target.dataset.src);
// Remove the iframe from the DOM, set the src attribute, and re-add it.
// This will not update the joint session history.
// Requires a phx-update=ignore wrapper element.
//
// let iframe = this.iframe();
// iframe.remove();
// iframe.setAttribute("src", e.target.dataset.src);
// this.el.append(iframe);
// BROKEN: Note, this version exhibits the bad behaviour of updating
// the joint session history. I am including it here to show that this
// problem is not specific to LiveView.
//
// this.iframe().src = e.target.dataset.src;
});
});
}
};
You could also check out Alpine.js and apply the same concept using some lightweight, inline expressions.