SVG sprites in helper function


#1

Hello,

I use svg sprites like this:

<svg><use href="combined.svg#filter_sent"></use></svg>

In a Meteor/Blaze template helper, svg sprites are not rendered:

color: function () {
    if (this.color && !this.validate) {
        return '<svg><use href="combined.svg#green"></use></svg>';
    }
    if (this.color && this.certain) {
        return '<svg><use href="combined.svg#orange"></use></svg>';
    } else {
        return '<svg><use href="combined.svg#red"></use></svg>';
    }
}

=> Inside the use > shadow-root , nothing is inserted.

Any idea?


#2

How do you insert the output of the helper? Normally helpers results are stripped of all HTML, if you don’t want that you need to use the helper in your Blaze templates with triple mustache, like {{{color}}}


#3

The helper is of course inserted like that

<div class="colorset">
    {{{color}}}
</div>

The html is well inserted but the svg not rendered inside the use tag.


#4

I believe this has to do with how SVG is rendered in the browser. By the time your helper fires, the DOM already has the SVG rendered, with the missing use tag, which is why it doesn’t show. Try to modify the DOM with javascript instead of using reactivity.


#5

The following worked. You can just modify the SVG elements via the DOM

svg.html

<template name="svg">
    <svg viewBox="0 0 400 100">
        <defs>
            <rect id="anim-rect"
                x="-25" y="-25"
                width="50" height="50"
                fill="#29e" >

                <animate
                    attributeName="fill"
                    values="#29e; #4e4; #f40; #29e"
                    dur="6s"
                    repeatCount="indefinite" />
            </rect>
        </defs>
        <use id="left" xlink:href="#anim-rect" transform="translate(100 50)"/>
        <use id="middle" xlink:href="#anim-rect" transform="translate(200 50)"/>
        <use id="right" xlink:href="#anim-rect" transform="translate(300 50)"/>
    </svg>
    <input type="checkbox" value="left" checked> Left
    <input type="checkbox" value="middle" checked> Middle
    <input type="checkbox" value="right" checked> Right
</template>

svg.js

import './svg.html';
import { Template } from 'meteor/templating';

Template.svg.onCreated(function(){
    const instance = this;
    const debugAction = `${instance.view.name}.onCreated`;
    console.log(debugAction);
});
Template.svg.onRendered(function(){
    const instance = this;
    const debugAction = `${instance.view.name}.onRendered`;
    console.log(debugAction);
});
Template.svg.events({
    'change input'(event, instance){
        const c = event.currentTarget;
        console.info(`${c.value} ${c.checked}`);
        instance.findAll(`#${c.value}`).forEach((element) => {
            element.style.display = c.checked ? '' : 'none';
        })
    },
});