svg icon indicating copy to clipboard operation
svg copied to clipboard

Runtime error when passing `class` attribute from Html package.

Open jwoudenberg opened this issue 8 years ago • 15 comments

When attempting to add a class name to an SVG element using class from the elm-lang/html package the compiler doesn't complain. When running the compiled program an error is thrown:

Uncaught TypeError: Cannot set property className of #<SVGElement> which has only a getter

It's a stupid mistake, but still, when working with some SVG content nested in an HTML view it's not unlikely to happen.

Below is a sample program that produces the error.

module Main exposing (..)

import Html.App as Html
import Svg exposing (..)
import Html.Attributes exposing (class)


view : () -> Svg Never
view model =
    svg []
        [ g [ class "html-class" ]
            []
        ]


main : Program Never
main =
    Html.beginnerProgram { model = (), view = view, update = \_ _ -> () }

jwoudenberg avatar May 21 '16 10:05 jwoudenberg

Happened to me as well.

doppioslash avatar Aug 10 '16 21:08 doppioslash

I had the same problem.

@evancz Why class functions from Html and Svg modules have incompatible implementations?

-- From Html.Attributes
-- className property can't be used for svg nodes
class value =
  VirtualDom.property "className" (Json.string value)

-- From Svg.Attributes
class value =
  VirtualDom.attribute "class" value

voltidev avatar Sep 23 '16 14:09 voltidev

SVG does not have JS properties. You can not use properties for anything.

I am just curious why people are mixing and matching between these libraries.

evancz avatar Sep 23 '16 17:09 evancz

In my case I wasn't intentionally mixing them so once I figured out what went wrong it was easy to fix. Still, it would have been nice if the compiler would have warned me for my stupidity.

jwoudenberg avatar Sep 24 '16 10:09 jwoudenberg

I pretty often use inline SVGs in my HTML and I can add class attribute to almost any element including SVG:

<div class="house">
  <svg class="dog">
    <path d="" />
  </svg>
</div>

So when I first time tried Elm, my intuition failed:

div [ class "house" ]
    [ svg [ class "dog", svgContent "<path d='' />" ] []
    ]

svgContent content =
    property "innerHTML" (Json.Encode.string content)

The compiler didn't tell me anything about it. So I got Uncaught TypeError: Cannot set property className... runtime exception. It's totally my fault coming from my wrong expectations and previous experience.

BTW, if Html.class implementation would also use VirtualDom.attribute "class" value approach, it would prevent the problem for other newcomers. I guess it relies on the className property for performance?

voltidev avatar Sep 24 '16 14:09 voltidev

I ran into this problem because I was using inline SVGs. Easy mistake to make any time you're using inline SVGs. Took some digging to realize what I was doing wrong.

paulstatezny avatar Oct 12 '16 22:10 paulstatezny

I am using inline SVGs a lot a also. I am really don't like this runtime exception since only because of this I am checking every page of my Elm project for this issue (and there still possible runtime issues when state changes for example).

The most bad thing is that elm compiler allows to pass Html.Attributes.class to functions with definition like this: icon : String -> List (Svg.Attribute msg) -> Svg msg

ssbb avatar Mar 19 '17 02:03 ssbb

I had same issue. It would be good if it could be caught by compiler, to help enforce "no runtime exceptions".

I think the issue is that both Svg.Attribute msg and Html.Attribute msg are type aliases, which don't enforce strong typing. Don't see an easy solution, without breaking changes. It would be good if elm had something like type alias that enforced strong typing (could use a union type with a single variant but it's a bit messy, and a breaking change).

derekdreery avatar Apr 01 '17 17:04 derekdreery

I just ran into this exact issue today, didn't take long to figure out but still confused because I got a runtime error instead of a compiler error.

zachrburke avatar Sep 10 '17 22:09 zachrburke

Here's what surprised me: image

According to the source, Svg.svg accepts List (Html.Attribute msg):

svg : List (Html.Attribute msg) -> List (Svg msg) -> Html.Html msg

Requisite SSCCE in Ellie.

My use is embedding SVG in HTML too. I mistakenly added Html.Attribute.class to Svg.svg.

To fix it I added a wrapper HTML element (span) with the class.

absynce avatar Jan 12 '18 18:01 absynce

I've just ran into the same issue.

Accidentally used Html.Attribute.class instead of TypedSvg.Attributes.class.

Yes, it caused a runtime error which was surprising and somewhat disappointing. People are running into this, see the referenced tickets. I also arrived here from such a ticket.

I would suggest going ahead with a breaking change to ensure that the type system can still protect us from runtime errors.

viktor-ferenczi avatar Mar 26 '19 03:03 viktor-ferenczi

Just wanted to leave here that the same thing happened to me, took me a while to figure out that I had my imports messed up.

I feel like since these types are not compatible, the code shouldn't have compiled (or maybe give a warning). It's a bit sad to see that people have had this issue for 3,5 years now.

OscarMulder avatar Dec 28 '19 19:12 OscarMulder

Hello from 2020 (what a great year!), I've just spent over an hour wondering why my page fails unexpectedly (and actually goes into infinite loop of updateIfNeeded), just because I accidentally imported Html.Attributes.class instead of Svg.Attributes.class which the compiler happily accepted :-( I got used so much to Elm's "If it compiles it just works" so I was quite taken aback by this. Not sure which is the correct place to push for fix, whether here or at the elm/compiler but I guess this should really get fixed. Seems like I'm not the only one who stumbled upon this...

matobet avatar Nov 25 '20 16:11 matobet

Greetings from 2022 :wave:

This bit us as well. Interestingly, this did not cause a fatal runtime error during the development build with the --debug flag on, and only error-ed out for the production build, which made it significantly more nasty for us

abradley2 avatar Jun 13 '22 11:06 abradley2

I'm not even using Elm anymore. I guess the ecosystem has just stalled due to the Elm 0.19 release fiasco. These issues may never be fixed.

viktor-ferenczi avatar Jun 13 '22 15:06 viktor-ferenczi