javascriptsvgweb-componentcustom-elementhtml-imports

Can I get the contents of a use element that is referencing an external svg?


I am building a web component that renders svg icons onto the page in Shadow Dom. i.e.

<ba-icon i="airplane"></ba-icon>

I have an external svg sprite file, that has a ton of SVG icons in it.

The internals of the web component render the following into Shadow Dom:

<svg>
    <use xlink:href="i.dist.svg#i-airplane"></use>
<svg>

Everything is correctly rendering on the screen, but I am after some information that is embedded inside of the SVG, specifically the information contained in the viewbox, (for example: viewBox="0 0 32 32").

I know that what is rendered in the use is input into the Shadow Dom as well. But I am trying to find another way of obtaining the information embedded into the use. I tried to ajax the contents of the svg, but this is turning into a big problem for multiple icons on the page since each instance of the web component is now making that call. How else could I do this?

For reference:

enter image description here


Solution

  • Actually there are manys ways to acheive this, depending of the structure of the SVG file you use, and what you want to do.

    With SVG sprites as an external file, you can take profit of the HTML Imports technology to parse the file:

    <head>
    ...
      <link id="ic" rel="import" href="i.dist.svg">
    
      <script>
        document.registerElement( "ba-icon", { 
            prototype:  Object.create( HTMLElement.prototype, {
                createdCallback: {
                    value: function () 
                    {
                        var name = "i-" + this.getAttribute( 'i' )
                        var sh = this.createShadowRoot()
                        sh.innerHTML = '<svg><use xlink:href="i.dist.svg#' + name + '"/>'
                        this.setAttribute( "i-viewBox", ic.import.querySelector( 'svg#' + name ).getAttribute( "viewBox" ) )
                    }
                }
            } )
        } )
      </script>
    </head>
    

    The SVG file is not imported twice because it is cached by the browser.

    Note: This solution (using <use>) may not be the fastest but it is the simplest to code, and to understand. It depends on what you really want to do with the attributes (and when).