Optiq
Optiq

Reputation: 3182

Can we render Angular components inside of our SVG templates?

Seeing that we can save our template files as .svg rather than .html now I figured I could make svg components that could be used as follows.

main.component.svg

<svg>
    <my-svg-component></my-svg-component>
</svg>

mySvg.component.svg

<text x="0" y="60">test text</text>

I got an error saying <text></text> wasn't a recognized element so I modified it to this

<svg:text x="0" y="65">test text</svg:text>

The error went away however nothing is rendering. I added the script directly into the <svg> tag in the main.component.svg file without the svg: at the beginning and it worked fine.

Is there something I should be doing in the mySvg.component template to make this work as a reusable component or do we have to generate all the SVG inside one template?

UPDATE

I tried using SVG's <foreignObject> like so

<svg>
    <foreignObject>
        <my-svg-component></my-svg-component>
    </foreignObject>
<svg>

this didn't work either. I tested it out with a paragraph tag and noticed I had to use <xhtml:p> in order for it to render. I tried adding the xhmtl: part to my component for grins and giggles and still didn't see anything render. Now I'm wondering if there's an angular: of some form that can be used.

Upvotes: 6

Views: 5440

Answers (1)

Sergey Rudenko
Sergey Rudenko

Reputation: 9227

You could do that this way:

template:

<svg>
  <g svgtext></g>
</svg>

svg component:

import { Component } from '@angular/core';

@Component({
  selector: '[svgtext]',
  template: `<svg:text x="0" y="65">test text</svg:text>`,
  styles: [`your styles come here`]
})
export class HelloComponent  {

}

So the trick is to attach your svg component to another svg element (group - g) via attribute selector. This way resulting template is valid SVG and you can get your text rendered.

See here: https://stackblitz.com/edit/angular-fd1tcd

If you do component selector with tags, than SVG schmema is broken and browser won't be able to render SVG. Using group (which is a valid svg container) we avoid that issue and the additional component html gets injected right inside such a group.

You can read this fantastic article by Tero (pretty old now) for more insights: https://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Upvotes: 24

Related Questions