# Load SVG externally and wire to elm model

**URL:** <https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842>\
**Category:** Learn\
**Created:** [February 3, 2021, 8:58am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842 "2021-02-03T08:58:32Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![shiningflint](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/shiningflint/32/3619_2.png) [@shiningflint](https://discourse.elm-lang.org/u/shiningflint)\
**Post date:** [February 3, 2021, 8:58am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/1 "2021-02-03T08:58:32Z")

</div>

Hello everyone, coming from Vue, I have been learning elm for the past 4 months and having a great time so far! But I am stuck on achieving one idea I have in elm.

The idea is:

1. Load an SVG file externally and append it inline.
2. Collect SVG elements by querying id names within.
3. Attach onClick listeners to those element collection.

Basically it tries to turn any SVG drawing into clickable checkboxes (if it has the correct ID names).

Before this, I was experimenting around using predefined div elements. The model being a tuple of List & Set  
[https://ellie-app.com/cgjnTJ2XfmRa1](https://ellie-app.com/cgjnTJ2XfmRa1)

I have zero idea on how it works and I have yet to experiment this with vanilla JS.

Thanks!

---

<div class="post-metadata">

**Author:** ![rupert](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/rupert/32/1775_2.png) [@rupert](https://discourse.elm-lang.org/u/rupert)\
**Post date:** [February 3, 2021, 9:18am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/2 "2021-02-03T09:18:28Z")

</div>

I have never tried it with SVG, but this might help:

[https://package.elm-lang.org/packages/hecrj/html-parser/latest/](https://package.elm-lang.org/packages/hecrj/html-parser/latest/)

---

<div class="post-metadata">

**Author:** ![shiningflint](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/shiningflint/32/3619_2.png) [@shiningflint](https://discourse.elm-lang.org/u/shiningflint)\
**Post date:** [February 4, 2021, 6:55am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/3 "2021-02-04T06:55:41Z")

</div>

Thanks rupert! It is said it doesn’t support svg in the parser, but tried it out anyway. It failed to render even though the inner HTML shows the SVG inside the browser’s inspector.

I’ve come across to this package [SvgParser - elm-svg-parser 1.0.0](https://package.elm-lang.org/packages/Garados007/elm-svg-parser/latest/SvgParser)

It has this `toAttribute` endpoint which I can see myself wiring the color attribute to the model. Still has left me wondering around how to attach onClick messages. I’ll figure it out eventually.

Thanks for the package recommendation. It helped me see how to proceed solving this problem!

---

<div class="post-metadata">

**Author:** ![francescortiz](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/francescortiz/32/1721_2.png) [@francescortiz](https://discourse.elm-lang.org/u/francescortiz)\
**Post date:** [February 9, 2021, 10:40pm UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/4 "2021-02-09T22:40:06Z")

</div>

You can write a custom onClick listener that passes the target’s `id` to the event.

---

<div class="post-metadata">

**Author:** ![yosteden](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/yosteden/32/5113_2.png) [@yosteden](https://discourse.elm-lang.org/u/yosteden)\
**Post date:** [February 10, 2021, 12:19am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/5 "2021-02-10T00:19:11Z")

</div>

Yes @shiningflint elm-svg-parser is definitely the way to go. I’ve done almost exactly the same thing as you’re asking for. A false start that made things miserable for a little while was to use `img` tags and use ports with something like [GitHub - iconic/SVGInjector: Fast, caching, dynamic inline SVG DOM injection library](https://github.com/iconic/SVGInjector). Although this makes loading images nearly trivial, this plays poorly with the virtual DOM.

Instead I would recommend loading the SVG as a string through `Http` and biting the bullet for the additional record-keeping that will entail then passing it through the `SvgParser`. _Don’t_ use `SvgParser.parse`, because you’ll end up directly with `Html` which cannot be inspected and therefore you can’t traverse over the SVG nodes and add click handlers as necessary.

Instead you want to use `SvgParser.parseToNode`, which gives you `SvgNode`s that you can then play with. Unfortunately `SvgParser` doesn’t expose a function to go from `SvgNode` to `Html a`, so you’ll want to copy part of `SvgParser.parse` in particular

```auto
            case svgNode of
                SvgElement element ->
                    if element.name == "svg" then
                        Ok <|
                            svg (List.map toAttribute element.attributes)
                                (List.map nodeToSvg element.children)

                    else
                        Err "Top element is not svg"

                _ ->
                    Err "Top element is not svg"

```

and put that in a separate function to get `SvgNode -> Html msg`.

To add the onclick handler you can modify the above snippet of code to inspect certain attribute strings and translate them to actual `onClick MyCustomType` `Html.Attribute`s (e.g. you could have have the `SvgAttribute` `("myOnClick", "onClickValue")` and then wrap `toAttribute` with something that checks for `"myOnClick"` and `"onClickValue"` and calls `onClick OnClickValue`.

---

<div class="post-metadata">

**Author:** ![shiningflint](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.elm-lang.org/shiningflint/32/3619_2.png) [@shiningflint](https://discourse.elm-lang.org/u/shiningflint)\
**Post date:** [February 10, 2021, 6:54am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/6 "2021-02-10T06:54:39Z")

</div>

Thank you for the suggestions everybody. After spending some days with it, I found the solution I need. I wrote an oversimplified version of the solution in this Ellie snippet. Hopefully it can be some reference for future people including future me.  
[https://ellie-app.com/ckpfYCRq7k7a1](https://ellie-app.com/ckpfYCRq7k7a1)

Some points noted:

1. I’m glad the SvgParser package exposes the custom type, because I need to override the `nodeToSvg` & `elementToSvg` functions.
2. Looking in the source code, the `nodeToSvg` recursion parsing logic is not as scary as I thought.
3. As @yosteden mentioned, the svg is going to be loaded through `Http`. And the mapping between id configurations will come from the `flags` configuration for the initial model.

So, yay! Making this work in elm feels so good!

---

<div class="post-metadata">

**Author:** ![system](https://canada1.discourse-cdn.com/flex035/uploads/elm_lang/original/1X/50a05e53677a2c3b47776d7abd0f113eb50193a1.png) [@system](https://discourse.elm-lang.org/u/system)\
**Post date:** [February 20, 2021, 6:54am UTC](https://discourse.elm-lang.org/t/load-svg-externally-and-wire-to-elm-model/6842/7 "2021-02-20T06:54:48Z")

</div>

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.
