Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: SVG elements (text and shapes) in the repeat directive are not rendered by the browser #6599

Open
uivanovic opened this issue Jan 12, 2023 · 3 comments
Labels
community:help-wanted Valuable contributions not currently worked on by the core team status:needs-investigation Needs additional investigation

Comments

@uivanovic
Copy link

uivanovic commented Jan 12, 2023

🐛 Bug Report

When trying to render SVG elements (text and shapes) from within the repeat directive, the nodes are present in the DOM but they are not rendered by the browser. Elements outside of the repeat directive are correctly rendered.

The following two screenshots highlight some of the differences between the working element (from outside the repeat directive) and a non-working element (from inside the repeat directive):

  • Styles are applied to the working element but not applied to the non-working one
  • There's a subtle difference in tagName and nodeName of the elements

Working element:

Screenshot 2023-01-10 at 15 48 08

Non-working element:

Screenshot 2023-01-10 at 15 48 16

💻 Repro or Code Sample

https://stackblitz.com/edit/node-nszhmz?file=src%2Fjs%2Ftag%2Ftag.ts,src%2Ftemplates%2Findex.html,src%2Fjs%2Ftag%2Ftag.ts&v=1

🤔 Expected Behavior

SVG elements are rendered as expected

😯 Current Behavior

SVG element DOM nodes are present in the DOM but not recognized/rendered by the browser

💁 Possible Solution

Might have something to do with SVG namespaces. Attributes in SVG elements might need to be set with setAttributeNS instead of setAttribute. There are several somewhat similar issues on StackOverflow and other forums that point to namespaces as a potential issue.

🔦 Context

FAST components don't seem to be able to dynamically render SVG elements from the repeat directive. Reproduced in Chrome, Firefox (locally + stackblitz) and Safari (locally).

🌍 Your Environment

  • MacOS Monterey 12.3.1 (21E258)
  • Chrome Version 107.0.5304.121 (Official Build) (x86_64)
  • Firefox 108.0.2 (64-bit)
  • Safari Version 15.4 (17613.1.17.1.13) (Stackblitz unfortunately doesn't work in Safari but I reproduced it locally)
@uivanovic uivanovic added the status:triage New Issue - needs triage label Jan 12, 2023
@KingOfTac KingOfTac added status:needs-investigation Needs additional investigation community:help-wanted Valuable contributions not currently worked on by the core team and removed status:triage New Issue - needs triage labels Jan 12, 2023
@KingOfTac
Copy link
Collaborator

KingOfTac commented Jan 12, 2023

This may be browser limitation since svgs are not actually html but an xml syntax. This needs more investigating to know for sure.

@uivanovic
Copy link
Author

uivanovic commented Jan 12, 2023

Thanks for the quick response @KingOfTac. Here's a short snippet for reference that generates a dynamic SVG in native JS, and highlights the difference between createElementNS and createElement

let textColors = ['red', 'green', 'black', 'blue', 'magenta']

let svgElNS = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svgElNS.setAttribute('viewBox', '0, 0, 240, 240');
svgElNS.setAttribute('width', '240');
svgElNS.setAttribute('height', '240');
document.body.appendChild(svgElNS);

// text nodes created via createElementNS are rendered correctly
for (let i=0; i<textColors.length; i++) {
    let textElNS = document.createElementNS('http://www.w3.org/2000/svg', 'text');
    textElNS.setAttribute('x', '30');
    textElNS.setAttribute('y', String(15 + 15 * i));
    textElNS.setAttribute('fill', textColors[i]);
    textElNS.setAttribute('transform', 'rotate(30 20,40)');
    textElNS.innerHTML = 'Text el with NS';
    svgElNS.appendChild(textElNS);
}

// text nodes created via createElement can be seen in the DOM but are not rendered
for (let i=0; i<textColors.length; i++) {
    let textEl = document.createElement("text");
    textEl.setAttribute('x', '90');
    textEl.setAttribute('y', String(15 + 15 * i));
    textEl.setAttribute('fill', textColors[i]);
    textEl.setAttribute('transform', 'rotate(30 20,40)');
    textEl.innerHTML = 'Text el without NS';
    svgElNS.appendChild(textEl);
}
dynamic-svg-elements-native-js.mov

@janechu
Copy link
Collaborator

janechu commented Nov 4, 2024

Some insight into what is going on under the hood here, we are creating a DocumentFragment from whatever is inside an individual html tagged template literal. Since the repeat has it's own distinct html template, the browser (and FAST) does not have the additional context that the contents are svg. This results in this issue as it is assumed that it is html. For now I would suggest some workarounds by creating a string with your svg elements and inserting it into the same html template that contains the svg.

This is still an issue we will address in future, however it's not high on the priority list. If you'd like to propose and contribute a fix I would suggest the creation of an svg tagged template literal so that any other non-html namespaces can follow a similar pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
community:help-wanted Valuable contributions not currently worked on by the core team status:needs-investigation Needs additional investigation
Projects
None yet
Development

No branches or pull requests

3 participants