Skip to content

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

Open
@glennsl

Description

@glennsl

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 )

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions