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:
- Load an SVG file externally and append it inline.
- Collect SVG elements by querying id names within.
- 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
I have zero idea on how it works and I have yet to experiment this with vanilla JS.
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
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!
You can write a custom onClick listener that passes the target’s
id to the event.
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. 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
SvgNodes that you can then play with. Unfortunately
SvgParser doesn’t expose a function to go from
Html a, so you’ll want to copy part of
SvgParser.parse in particular
case svgNode of
SvgElement element ->
if element.name == "svg" then
svg (List.map toAttribute element.attributes)
(List.map nodeToSvg element.children)
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
Html.Attributes (e.g. you could have have the
("myOnClick", "onClickValue") and then wrap
toAttribute with something that checks for
"onClickValue" and calls
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.
Some points noted:
- I’m glad the SvgParser package exposes the custom type, because I need to override the
- Looking in the source code, the
nodeToSvg recursion parsing logic is not as scary as I thought.
- 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!
This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.