Repository navigation
Error when using x-for to generate SVG elements #637
Copy link
Copy link
Closed
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation
Description
Alpine version: 2.4.1
I'm getting an error when using x-for on a template tag to generate SVG elements. With the following HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rectangle Editor</title>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@2.4.1/dist/alpine.js"></script>
</head>
<body>
<div x-data="rectangleEditor()">
<svg width="1024" height="1024">
<!-- Error -->
<template x-for="rectangle in rectangles" :key="rectangle">
<rect :x="rectangle.x" :y="rectangle.y" :width="rectangle.width" :height="rectangle.height" />
</template>
</svg>
<!-- No error -->
<template x-for="rectangle in rectangles" :key="rectangle">
<div :x="rectangle.x" :y="rectangle.y" :width="rectangle.width" :height="rectangle.height" />
</template>
</div>
<script>
function rectangleEditor() {
return {
rectangles: [
{ x: 20, y: 40, width: 200, height: 400 },
{ x: 60, y: 100, width: 500, height: 500 },
{ x: 200, y: 40, width: 100, height: 400 },
{ x: 300, y: 40, width: 100, height: 400 },
],
}
};
</script>
</body>
</html>I don't get such an error when using x-for outside a svg element. But as soon as I add elements in a svg element using x-for (even standard HTML elements such as div), I get the following stack trace:
Chromium 81:
alpine.js:76 Uncaught TypeError: Cannot read property 'childElementCount' of undefined
at warnIfMalformedTemplate (alpine.js:76)
at handleForDirective (alpine.js:438)
at alpine.js:1570
at Array.forEach (<anonymous>)
at Component.resolveBoundAttributes (alpine.js:1530)
at Component.initializeElement (alpine.js:1446)
at alpine.js:1430
at alpine.js:1420
at walk (alpine.js:84)
at walk (alpine.js:88)
Firefox 78:
Uncaught TypeError: el.content is undefined
alpinejs 2.4.1/dist/alpine.js:76
alpinejs 2.4.1/dist/alpine.js:438
alpinejs 2.4.1/dist/alpine.js:1570
alpinejs 2.4.1/dist/alpine.js:1530
alpinejs 2.4.1/dist/alpine.js:1446
alpinejs 2.4.1/dist/alpine.js:1430
alpinejs 2.4.1/dist/alpine.js:1420
alpinejs 2.4.1/dist/alpine.js:84
alpinejs 2.4.1/dist/alpine.js:88
alpinejs 2.4.1/dist/alpine.js:88
alpinejs 2.4.1/dist/alpine.js:1408
alpinejs 2.4.1/dist/alpine.js:1425
alpinejs 2.4.1/dist/alpine.js:1355
alpinejs 2.4.1/dist/alpine.js:1735
alpinejs 2.4.1/dist/alpine.js:1678
alpinejs 2.4.1/dist/alpine.js:1694
alpinejs 2.4.1/dist/alpine.js:1693
alpinejs 2.4.1/dist/alpine.js:1677
If this isn't supported, then this should be documented in the README. (I'm willing to open a PR for that if this is the case.)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
documentationImprovements or additions to documentationImprovements or additions to documentation
Activity
allmarkedup commentedon Jul 7, 2020
FWIW I suspect this is not an Alpine issue - if you are using HTML tags (like
template) inside an SVG element they will have an SVG namespace so HTML elements likeHTMLTemplateElementwon't be implemented by the browser. I ran into something similar a while back trying to use vanilla JS and templates in SVG elements.Edit: Sounds like Polymer ran into something similar and there is now a WHATWG feature request open to provide support: whatwg/html#3563 - not much help in the short term though.
SimoTod commentedon Jul 7, 2020
Yeah, it's a DOM issue. templates inside an svg tag are not implemented and they miss the content property (you can see it using the inspector without alpine).
You need to include a polyfil like the one below (adapted from one mentioned on the polymer issue)
Calinou commentedon Jul 7, 2020
@SimoTod That polyfill seems to be working (tested in Firefox and Chromium). Thanks a lot 🙂
SimoTod commentedon Jul 7, 2020
No worries. Make sure you test it on all browsers you support (IE11, old edge, Safari, etc). It should work but I did not check. 👍
Document how to use `template` in `svg` elements using a polyfill
Document how to use `template` in `svg` elements using a polyfill
Document how to use `template` in `svg` elements using a polyfill
Corkle commentedon Dec 19, 2020
I'm curious why
x-foris only supported ontemplatetags. Is this due to a technical limitation? It would be nice to be able to use it on other tag types that are supported withinsvg.Calinou commentedon Dec 19, 2020
Yes, Alpine.js doesn't use a virtual DOM which means you can only use
x-forontemplatetags.HugoDF commentedon Dec 20, 2020
Hmmm I don't think it's strictly VDOM vs not, I think it's a trade-off (admittedly partly due to no VDOM). You probably could have an
x-forwithouttemplatebut you would need to hide the relevant Nodes/elements untilx-forhas run. The big benefits oftemplateis that by default it doesn't show visually and is easy to use to generate DOM Nodes.ocharles commentedon May 21, 2022
Edit: sorry, you can ignore this comment. I was applying the polyfill too early.
Here's an updated example that works:
For posterity, here's my original comment:
Details
Can anyone supply a small example page using `x-for` with `svg` and the latest Alpine? With the polyfill above, I still get errors.This is what I'm trying at the moment:
flytreeleft commentedon May 1, 2026
Actually, if you are using Vite, the
<template/>in<svg/>will cause[vite] Internal server error: Cannot read properties of undefined (reading 'nodeName').To avoid this error, you can add a namespace to the template tag (example
<x:template/>), then change your initialization code as following (based on #3944):If your
<svg/>is nested in<template/>, you should callrecreateTemplateInSvgrecursively with thecontentof<template/>node, becausequerySelectorAllwill not match the elements which are in<template/>.