Open ChristophP opened 6 years ago
Update
After giving this a lot of thought, I would like to suggest to add an additional check in the vdom to prevent the default on link clicks only when this is also true:
domNode.getAttribute('href')[0] !== '#'
This will preserve regular browser behavior for links which just reference an anchor and won't send the msg to the Browser.application. This will take care of the most common case for using anchor (go to anchor on same route) which is case 1
talked about above. Of course there are also other cases like going to a new page with an anchor (case 2 above) but those will need to be handled anyway in SPAs and the jump to the anchor needs to be delayed until the anchor is rendered.
This suggested fix could be a good way to get some of the browser fragment link behavior back that is now taken away by the prevent default.
I would advice against that. In our application we have custom logic which also allows us to scroll nested scrolled containers. All you need to do is to define the url parser in a way it parses fragments and do implement the logic appropriate to what you want to do. If elm would start ignoring these links it would be much harder for us to implement the scrolling in anything other than window.
By setting target "_self"
on links, Browser.application
seems to ignore them for navigation. So, that's a simple workaround which also works for mailto:
and tel:
links!
BTW: Thanks to @ChristophP for solving this issue on his own ;)
Yup, it's this line for reference https://github.com/elm/browser/blob/master/src/Elm/Kernel/Browser.js#L157
For a
Browser.application
the docs recommend to handleUrlRequest
like thisHowever, this won't do anything with links like the following
<a href="#someAnchor">Jump</a>
(to jump to<a name="someAnchor"></a>
) since they will count asInternal
UrlRequests. It is possible to jump to fragments usingNav.load
but the suggested code above will only change the url withNav.pushUrl
.Notes: There are a couple of cases to consider, links like:
#myAnchor
or/samePage#myAnchor
Links pointing to anchors on the same page can be used to safely jump to the anchor immediately using the browsers default behavior, because the page is already rendered./newPageAnchor#anchorOnDifferentPage
However when navigating to an new page an anchor on a new page, SPAs behave differently than server rendered pages. The url changes first and only after some async data is loading the page containing the anchor is actually rendered. Only once the page is rendered it is possible to jump to the anchor. This case introduces a time gap between clicking the link and being able to navigate to the anchor.It would be nice to have a solution for the first case that is close to browser behavior, but the
preventDefault
on every link seems to make it tough right now. The second case (navigating to a new page) doesn't seem to be elm specific but a general SPA "problem". Other frameworks and routers have similar issues https://github.com/rafrex/react-router-hash-link/tree/react-router-v2/3#react-router-hash-link-scroll and seem to use some kind of polling of the DOM to check if the anchor has been rendered.