1

I am trying to insert some SVG icons in the dom but the SVG(parent node) is always being replaced by the use(child node). Anyone help me figure it out?

Source code Image here

Codepen here

const icons = [
    "html5" ,
    "css3" ,
    "javascript" ,
    "bootstrap" ,
    "sass" ,
    "node" ,
    "mongodb" ,
    "d3" ,
    "react" ,
    "webpack" ,
    "wordpress"
];

const tech_icons = document.querySelector( "#techs__icons" );

icons.forEach( icon=> {

    const svg = document.createElement( "svg" );
    const use = document.createElement( "use" );

        svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );

    tech_icons.appendChild( use ).appendChild( use );

} );

I can successfully log them in the console but they don't seem to appear on the document.

I appended it already to the parent node (techs_icons) but can't figure it out at this point!

UPDATED CODE

icons.forEach( icon=> {

    const tech_icons = document.querySelector( "#techs__icons" );

    const svg = document.createElement( "svg" );
    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    const use = document.createElement( "use" );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );

    svg.appendChild( use );

    tech_icons.appendChild( svg );

} );

This snapshot seems to work here

Still won't be displayed in the DOM. Actually, they are being appended because when I hover them over in the inspector they are there but not visible.

SECOND UPDATE TO THE CODE

It looks like you need to create some kind of "fake" element inside my svg>use>"fake element", like a shadowRoot which i actually do not understand why the browser creates such an element when importing SVG files!

I figured it out when inspecting the element and saw that the browser actually creates automatically that shadow.

SVG

<symbol id="icon-html5">
   <path d="M2 0h28l-2.547 28.751-11.484 3.249-11.419-3.251-2.551-28.749zM11.375 13l-0.309-3.624 13.412 0.004 0.307-3.496-17.568-0.004 0.931 10.68h12.168l-0.435 4.568-3.88 1.072-3.94-1.080-0.251-2.813h-3.479l0.44 5.561 7.229 1.933 7.172-1.924 0.992-10.876h-12.789z"/>
 </symbol> 

Inspected code showing the auto created shadow element

const tech_icons = document.querySelector( "#techs__icons" );
const fragment = document.createDocumentFragment();

icons.forEach( icon => {

    const svg = document.createElement( "svg" );
    const use = document.createElement( "use" );
    let shadow = use.attachShadow( { mode : open } );

    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );
    use.setAttribute( "href" , `./src/images/sprites.svg#icon-${icon}` );
    shadow.appendChild( "I am a: child element inside shadowroot (svg>use>shadowroot>ME)" );

   svg.appendChild( use );

   fragment.appendChild( svg );

});

tech_icons.appendChild( fragment );

So at this point to recap:

  1. Added the result for the forEach() loop to a document fragment and after that loop ended i appended that fragment as a child to the real DOM element (.techs_info)
  2. Created a shadow and also append it as a child to the use element

Problem still exists, while when appending the shadow to the use element neither the DOM or the console does not actually display anything!

Evan
  • 583
  • 1
  • 5
  • 11

4 Answers4

1

SVG elements are not standard HTML so you'll need to specify the SVG namespace in the createElementNS() method:

const svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' )
const use = document.createElementNS( 'http://www.w3.org/2000/svg', 'use' )

Also in the SVG source file you must specify the namespace in the xmlns attribute:

<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="icon-html5">
   <path d="M2 0h28l-2.547 28.751-11.484 3.249-11.419-3.251-2.551-28.749zM11.375 13l-0.309-3.624 13.412 0.004 0.307-3.496-17.568-0.004 0.931 10.68h12.168l-0.435 4.568-3.88 1.072-3.94-1.080-0.251-2.813h-3.479l0.44 5.561 7.229 1.933 7.172-1.924 0.992-10.876h-12.789z"/>
 </symbol> 
</svg>
Supersharp
  • 29,002
  • 9
  • 92
  • 134
1
componentDidMount (){

    const script = document.createElement("script");
    const script1 = document.createElement("script");
    const script2 = document.createElement("script");

    script.src = 'assets/js/jquery.showmore.js';
    script1.src = 'assets/js/showmore.js';
    script2.src = 'assets/js/owl-carousel.js';
    script.async = true;
    script1.async = true;
    script2.async = true;

    document.body.appendChild(script);
    document.body.appendChild(script1);
    document.body.appendChild(script2);
}
Peyman Mohamadpour
  • 17,954
  • 24
  • 89
  • 100
0

I played around with your Codepen using this corrected code:


const icons = [
    "html5" ,
    "css3" ,
    "javascript" ,
    "bootstrap" ,
    "sass" ,
    "node" ,
    "mongodb" ,
    "d3" ,
    "react" ,
    "webpack" ,
    "wordpress"
];

icons.forEach( icon=> {
    const tech_icons = document.getElementById( "techs__icons" );

    const svg = document .createElementNS("http://www.w3.org/2000/svg", "svg");
    svg.setAttribute( "class" , `techs__icon icon icon-${icon}` );

    const use = document .createElementNS("http://www.w3.org/2000/svg", "use");
    use.setAttribute( "xlink:href" , `./src/images/sprites.svg#icon-${icon}` );

    svg.appendChild( use );

    tech_icons.appendChild( svg );

  console.log(tech_icons);
} );

When inspecting in the console, the SVG elements are created and occupy space in the DIV in the document but they seems to be empty or invisible. So I blame the sprites.svg file.

igreka
  • 330
  • 3
  • 15
  • The problem my friend is that i already tested the sprites and are working fine! I mean i had it previously hard coded all the icons and now i am trying to add them dynamically to the DOM. – Evan Apr 17 '19 at 11:03
  • Where can I access the .svg file in your Codepen? I couldn't find it. Maybe I could investigate a little more with it on hands. – igreka Apr 17 '19 at 16:14
  • Hey @igreka i just updated the post. It includes also the svg source code. – Evan Apr 18 '19 at 07:11
-1
var mylist = document.getElementById("myList")
list.forEach(item){
var node = document.createElement("LI");                 // Create a <li> node
var textnode = document.createTextNode(item);         // Create a text node
node.appendChild(textnode);                          // Append the text to <li>
mylist.appendChild(node) //Append to<Ul> id="myList"
}