Links in shadow DOM aren’t routed and don’t transition


#1

I’m working on a Discourse plugin (which uses Ember) and noticed the following: Navigation triggered by links from inside a shadow tree aren’t transitioning as they would without being in a shadow DOM. Instead, a regular request is performed and regular navigation happens as it would in a non-SPA.

I didn’t find any information on that, so I have no glue where to start looking. One important note: Discourse currently uses Ember version 2.13.3 which is quite old.

Is that a known problem or fixed in a future version? Or doesn’t Ember have any means of reacting to navigation being triggered inside a shadow DOM?


#2

In general, a plain <a> in an Ember app will trigger a normal navigation. To get in-app transitions, one must use either {{link-to}} or write an action handler that calls transitionTo on the router service.

Events bubble out of shadow DOM, so you can capture the clicks as they escape shadow DOM and call transitionTo (and preventDefault so there’s no full page transition). But that assumes Discourse lets you put an action handler outside the shadow DOM – I’m not familiar with the exact plugin rules. This seems like a general thing that any Discourse plugin might want, and it may be best solved by Discourse itself.

(There is are popular addons like ember-href-to that change the situation and make all links to valid Ember routes into in-app transitions by capturing the clicks. And there is an active RFC to make this the default behavior for all Ember apps.)


#3

Thank you for that detailed answer. Let me clarify two things:

  • I use shadow DOM in the plugin; otherwise, Discourse doen’t use shadow DOM itself. I am therefor able to interact with it, capture events and process them.

  • All navigation in my plugin (i.e. via <a href="">) is handled with in-app transitions by default. I don’t explicitly use {{link-to}} or transitionTo for that. This only changes when introducing shadow DOM in my plugin.

    In that case, maybe Discourse is responsible for making regular links transition instead of triggering regular navigation and it just happens not to handle links inside a shadow DOM the same way.

I’ll dig around in the Discourse code to see if I can find anything related.

Update:

Discourse does indeed intercept all clicks on a elements from inside a #main element. Since events that escape the shadow DOM (e.g. the click event) are re-targetted to the shadow host element, my click events look like they originate from a div element and are therefor not intercepted by Discourse because it only looks for a elements.

TL;DR: This is a Discourse issue.