I am trying to use Lit-Element with a single slot wrapped by a SVG element.
But it seems that the <slot> located in the <svg> does not accept render the given SVG elements.
What does not work in a custom component:
render() {
return html`
<svg>
<slot><circle id="defaultCircle" cx=... cy=...></circle></slot>
</svg>`
}
Here is an example: https://stackblitz.com/edit/wy6bhj?file=index.html
Any idea why ? Any alternative ?
2019-02-18 COMMENTS
Justin Fagnani recommended to use a <foreignObject> to mix the HTML (that is the slot) with the SVG. Unfortunately, this doesn't work because in the slot it still SVG elements.
2019-02-19 UPDATE
Using the JavaScript expressing inside the render() function, I am trying to use this.children to iterate and add the children in the template. Now, using the inspector, it appears correctly in the DOM but nothing is rendered by the SVG element. I am lost and can't understand why the circle are not rendered.
https://stackblitz.com/edit/wy6bhj-hne7wl?file=my-element.js
2019-02-19 UPADTE2
I finally understood that there is no way I can do it the way a initially wanted. I opted to passe the SVG container as is.
<my-element>
<svg> ... </svg>
</my-element>
Then the <my-element> uses
const SVG_CONTAINER = this.children[0]
const NODES = SVG_CONTAINERS.children
To compute things. And voilà!
<slot> in an SVGSimplifying your code just to see what works.
Below is a native custom element that allows you to embed inner content. The inner content is an SVG. I added values into the SVG to get it to work.
class MyElement extends HTMLElement {
constructor() {
super();
const s = this.attachShadow({mode:'open'});
s.innerHTML = `<div>Your SVG</div>
<div style="border:1px solid blue;width:20px;height:20px;"><slot></slot></div>`;
}
}
customElements.define('my-element', MyElement);
<my-element>
<svg height="20" width="20">
<circle cx=10 cy=10 r=10 fill=red></circle>
</svg>
</my-element>
Now let's try doing this with the svg and not a div:
class MyElement extends HTMLElement {
constructor() {
super();
const s = this.attachShadow({mode:'open'});
s.innerHTML = `<div>Your SVG</div>
<svg height="20" width="20" style="border:1px solid blue;"><slot></slot></svg>`
}
}
customElements.define('my-element', MyElement);
<my-element>
<circle cx=10 cy=10 r=10 fill=red></circle>
</my-element>
If you dig into the Dev Tools you will see that the SVG refuses to accept a slot tag as a child. I didn't think that SVG allowed for <slot> and not I am sure. I just don't think you can do this the way you want.
The svg requirement time to render. Here is an alternative to your question. You can work around by using lifecycle. But ideally, you need to take another approach. Each svg should be competed and svg can have multiple svgs. For example, you can have an svg as a icons. A lit of svgs is an icon set which is your component.
Attached image
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With