flow icon indicating copy to clipboard operation
flow copied to clipboard

When using the Element API I want to be able to create SVG elements

Open heruan opened this issue 6 years ago • 17 comments

When creating components with the Element API I want to be able to create simple SVG elements, so I do not have to include other files and I can keep my source tree clean.

The Element API enforces attribute names to be lower case, but with SVG elements this may cause trouble since browsers are picky on SVG attribute case, e.g. Chrome won't render an <svg> with attribute viewBox written all lowercase.

This prevents creating SVG elements with the Element API, while a developer would expect to be able to do so in HTML5 documents e.g. as shown in MDN SVG element reference.

heruan avatar Nov 02 '17 17:11 heruan

Previously discussed in #1097. Not sure if the namespace is still an issue also

Artur- avatar Nov 02 '17 17:11 Artur-

This SO answer about HTML5 is very enlightening: https://stackoverflow.com/a/23322429/1006669

HTML is also namespace aware, but namespaces are assigned implicitly. HTML is converted to a DOM using an HTML parser, which knows which elements go in which namespace. That is, it knows that <div> goes in the http://www.w3.org/1999/xhtml namespace and that <svg> goes in the http://www.w3.org/2000/svg namespace.

Plus:

The HTML parser knows about HTML elements, SVG elements, and MathML elements and no others. There is no option to use elements from other namespaces, neither implicitly nor explicitly. That is, xmlns attributes have no effect.

So it seems like the Element API does not need any special handling of namespaces, it should just respect the right case for some SVG attributes and tags (MathML already has all lower-case attributes/tags).

heruan avatar Nov 02 '17 17:11 heruan

This is a comprehensive index of all SVG attributes and elements where they may appear:

https://www.w3.org/TR/SVG/attindex.html

heruan avatar Nov 03 '17 08:11 heruan

As a workaround, you could try creating a regular element as a wrapper, and then do element.setProperty("innerHTML", svgString);

Legioth avatar Nov 03 '17 09:11 Legioth

Any update on this?

As far as i understand the problem its caused by the way nodes and attributes are created on the client side (JavaScript):

document.createElement("svg"); is being called when we add a new Element to the UI. This creates an Tag inside the DOM but inside Chrome DevTools its listed as a "HTMLElement" (under "Properties") and won't render correctly.

If the element would be created by calling document.createElementNS("http://www.w3.org/2000/svg", "svg"); the Tag would look the same in DevTools but its correctly listed as a "SVGElement" and it gets rendered.

Same thing about adding attributes: setAttribute(...); puts an attribute in lowercase, as HTML is not case-sensitive while setAtributeNS(...); is case-sensitive.

tco42 avatar Dec 27 '18 22:12 tco42

I got the same problem. I thought it would be easy to just create a svg with elements. Someone found any hack/solution/workaround for this problem?

Thank you.

xasz avatar Mar 07 '19 15:03 xasz

Someone found any hack/solution/workaround for this problem?

https://github.com/vaadin/flow/issues/2842#issuecomment-341652190

Legioth avatar Mar 08 '19 12:03 Legioth

Still looking for a solution :)

xasz avatar Apr 02 '19 08:04 xasz

Any news on this? I need to render inline SVGs too.

RaimundBarbeln avatar Jul 04 '19 13:07 RaimundBarbeln

For me it seems that this is related to: #4644

Setting the outerHTML-Attribute "as it is actually" via javascript renders the svg correctly.

svg.getElement().executeJs("this.outerHTML= $0", svg.getElement().getOuterHTML());

Tolorio avatar Aug 03 '19 13:08 Tolorio

Any news? I would be interested as well.

alexanderboven avatar Jun 03 '20 09:06 alexanderboven

There has been quite many requests for SVG support, but this is not currently very high on our TODO list. I'd love to learn more about the needs so I could prioritise this properly.

  • What kind of use cases do you have for SVG. Static drawings or something dynamic with e.g. click listeners?
  • What kind of workarounds have you used? Custom client side componts? Plain JS from server-side? Assigning inner/outerHTML?

mstahv avatar Jan 14 '21 07:01 mstahv

A quite straight forward way is to create the SVG using LitElement, create a Java class for it and pass dynamic data through properties, as done e.g. in here

  1. https://github.com/Artur-/dynamic-svg/blob/master/frontend/fill-indicator.js
  2. https://github.com/Artur-/dynamic-svg/blob/master/src/main/java/com/example/app/FillIndicator.java

Artur- avatar Jan 14 '21 07:01 Artur-

OK I just lost almost a day over this bug. I was using the Html class to create a few simple <svg> elements and I thought there was something wrong with the CSS. If this is not going to be resolved anytime soon, please at least indicate in the Html class constructor javadoc that it can't be used to generate <svg> elements.

HermanBovens avatar Sep 16 '22 08:09 HermanBovens

We could even go one step further. We're already parsing the HTML on the server so we could explicitly look for usage of <svg> and throw an exception saying that it won't work.

Legioth avatar Sep 16 '22 11:09 Legioth

@Legioth I really have not the insight and knowledge about this, but could we not even find someone to actually make it work :)

xasz avatar Sep 16 '22 12:09 xasz

We could even go one step further. We're already parsing the HTML on the server so we could explicitly look for usage of <svg> and throw an exception saying that it won't work.

Well maybe it's better just to support it (2022 already), rather than throw an exception

kivan-mih avatar Oct 09 '22 15:10 kivan-mih

I created a draft PR to add trivial SVG support to Html, but only read-only: https://github.com/vaadin/flow/pull/15539. For that use case it might be though better to create a separate Svg component.

A proper support via Element API (as I think @heruan originally ment in this issue) would be great as well, would help to create some more advanced components.

mstahv avatar Dec 21 '22 17:12 mstahv

Also drafted the Svg component idea: https://github.com/vaadin/flow/pull/15540

mstahv avatar Dec 21 '22 17:12 mstahv

Status update: The master branch now contains Svg component to display images (and to allow styling them with css), but Element API still don't support SVG.

There is a start by @Legioth to fix this actual issue, but we'd still need to get rid of attribute name lowercasing (or some other workaround if we want to make the framework more complicated than would be required ;-) ): https://github.com/vaadin/flow/commit/9472e95710ed3741834198e15732113d1408c825

mstahv avatar Jan 11 '23 07:01 mstahv