Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clicking links (<a> elements) with href omitted or with an empty href incorrectly generates External UrlRequest's #55

Open
glennsl opened this issue Oct 8, 2018 · 6 comments

Comments

@glennsl
Copy link

glennsl commented Oct 8, 2018

Empty links, i.e. a elements without a href attribute or with href "" will cause External UrlRequests to be generated, and if handled as suggested in the Elm guide will cause page reloads.

This can be handled in update if you know about it, but is non-standard behavior that I think would surprise most people. it is also behavior that a lot of code depends on, among them elm-bulma, and it miight therefore not be immediately apparent what the cause is.

As far as I can understand, the standard behavior is:

  • When href is omitted it should not be considered a hyperlink (source)
  • When href is an empty string, it should be considered a reference to the beginning of the document (source)

My suggestion is to simply not emit a UrlRequest if href is omitted, and to emit an Internal UrlRequest if it is an empty string.

Here's a minimal, complete and verifiable example:

module Main exposing (main)

import Browser
import Browser.Navigation
import Html exposing (..)
import Url


type alias Model =
    ()


type Msg
    = UrlRequested Browser.UrlRequest
    | UrlChanged Url.Url


init () _ _ =
    ( (), Cmd.none )


update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )


view model =
    { title = ""
    , body = [ a [] [ text "click to reload" ] ]
    }


main =
    Browser.application
        { init = init
        , view = view
        , update = update
        , subscriptions = \_ -> Sub.none
        , onUrlRequest = UrlRequested
        , onUrlChange = UrlChanged
        }

My solution/workaround is to add a branch in update to do nothing on External "". For others coming across this looking for an easy fix, here's the fixed update function:

update msg model =
    case msg of
        UrlRequested (Browser.Internal _) ->
            ( model, Cmd.none )

        UrlRequested (Browser.External "") ->
            ( model, Cmd.none )

        UrlRequested (Browser.External url) ->
            ( model, Browser.Navigation.load url )

        UrlChanged _ ->
            ( model, Cmd.none )
@lydell
Copy link

lydell commented Oct 8, 2018

As far as I can tell, this is how things work in plain HTML:

  • clicking <a>test</a> does nothing (a.href === undefined)
  • clicking <a href="">test</test> is like refreshing the page (a.href === location.href)

@glennsl
Copy link
Author

glennsl commented Oct 8, 2018

clicking <a href="">test</test> is like refreshing the page (a.href === location.href)

Hmm, indeed. I'm not able to read that from the spec(s), though it seems Elm kind of accidentally does the right thing then. And while it would still seem technically correct to generate an Internal UrlRequest, perhaps that would just make it more cumbersome to get the expected behaviour. I'm not even sure what I'd consider expected behavior in an SPA though.

@MethodGrab
Copy link

This was reported on browser already: #34

@glennsl
Copy link
Author

glennsl commented Oct 10, 2018

Ah, thanks @MethodGrab! And a proposed fix is in elm/virtual-dom, so it seems the issue is well-covered.

I'd close this if it weren't for the issue with empty (as opposed to omitted) hrefs that's not covered by that issue and fix. I'll happily migrate this issue to a more suitable project though.

@evancz evancz transferred this issue from elm/compiler Nov 19, 2018
@davcamer
Copy link

davcamer commented Dec 6, 2018

I just ran in to this too, in the context of an a tag with an onClick attribute but no href specified at all. A possible fix, provided you aren't relying on fragment identifiers in the same context, is to add a href "#" attribute to the tag. This will trigger a URL that will be correctly recognized as internal.

@robx
Copy link

robx commented Apr 3, 2019

In the mean-time, a docs update would be highly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants