skip to Main Content

When I am trying to use the below code & dynamically pass the value to render the bar it does not show the svg with color :
below is the code for refrence

<template>
    <label>
      <strong>Test Bar1</strong>       
    </label>
    <svg height="24" width="400" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <linearGradient id="grayGradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#f5f5f5" />
          <stop offset="100%" stop-color="#e5e5e5" />
        </linearGradient>
        <linearGradient id="greenGradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#4dcb00" />
          <stop offset="100%" stop-color="#286900" />
        </linearGradient>
      </defs>
      <rect fill="url(#grayGradient)" x="0" y="0" width="100%" height="100%" rx="12" ry="12" />
      <rect id="greenId" fill="url(#greenGradient)" x="0" y="0" width="0%" height="100%" rx="12" ry="12" />
    </svg>
  
    <label>
      <strong>Test 2 Bar</strong> 
    </label>
    <svg height="24" width="400" xmlns="http://www.w3.org/2000/svg">
      <rect fill="url(#grayGradient)" x="0" y="0" width="100%" height="100%" rx="12" ry="12" />
      <rect id="greenId1" fill="url(#greenGradient)" x="0" y="0" width="0%" height="100%" rx="12" ry="12" />
    </svg>
  </template>

2

Answers


  1. Like commented you cannot have duplicate id values.

    Move the defs element out into is own SVG. The SVG should be hidden (here I set the width and the height to 0). Remove id values from the rect elements in the template and use class names instead.

    const menu = document.getElementById('bars');
    const temp1 = document.getElementById('temp1');
    
    addbar('Test bar 1', 70);
    addbar('Test bar 2', 33);
    
    function addbar(label, width){
      let clone = temp1.content.cloneNode(true);
      clone.querySelector('label strong').textContent = label;
      clone.querySelector('.greenbar').setAttribute('width', `${width}%`);
      menu.appendChild(clone);
    }
    div#bars {
      display: flex;
      flex-direction: column;
    }
    <div id="bars">
    </div>
    
    <svg width="0" height="0" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <linearGradient id="grayGradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#f5f5f5" />
          <stop offset="100%" stop-color="#e5e5e5" />
        </linearGradient>
        <linearGradient id="greenGradient" x1="0%" y1="0%" x2="100%" y2="0%">
          <stop offset="0%" stop-color="#4dcb00" />
          <stop offset="100%" stop-color="#286900" />
        </linearGradient>
      </defs>
    </svg>
    
    <template id="temp1">
      <label>
        <strong>Title</strong>       
      </label>
      <svg height="24" width="400" xmlns="http://www.w3.org/2000/svg">
        <rect fill="url(#grayGradient)" x="0" y="0" width="100%" height="100%" rx="12" ry="12" />
        <rect class="greenbar" fill="url(#greenGradient)" x="0" y="0" width="50%" height="100%" rx="12" ry="12" />
      </svg>
    </template>
    Login or Signup to reply.
  2. You can use duplicate id values in SVGs when you place the SVG in shadowDOM.

    No need to use LWC – Lightning Web Components for that

    A native Web Component <gradient-bar> to create the SVG is:

    <gradient-bar value="5" start="tomato" stop="red">React</gradient-bar>
    <gradient-bar value="30" start="red" stop="orange">Vue</gradient-bar>
    <gradient-bar value="70" start="red" stop="green">Svelte</gradient-bar>
    <gradient-bar value="100">Native Web Components</gradient-bar>
    <style>
      gradient-bar::part(percent) { fill:white; }
    </style>
    
    <script>
      customElements.define("gradient-bar", class extends HTMLElement {
        connectedCallback() {
          this.style.display = "block";
          let width = this.getAttribute("value") || 50;
          let r = this.getAttribute("r") || 1;
          this.attachShadow({mode:"open"}).innerHTML = `
    <style>:host{font-family:arial}</style>
    <strong part=title ><slot>[title goes here]</slot></strong>
    <svg viewBox="0 0 600 24">
      <defs>
        <linearGradient x2=100% id=back >
          <stop stop-color=#f5f5f5 /><stop stop-color=#e5e5e5 offset=100% />
        </linearGradient>
        <linearGradient x2=100% id=bar >
          <stop stop-color=${this.getAttribute("start")||"#4dcb00"} />
          <stop stop-color=${this.getAttribute("stop") ||"#286900"} offset=100% />
        </linearGradient>
      </defs>
      <rect part=back height=100% rx=${r}% fill=url(#back) width=100% />
      <rect part=bar  height=100% rx=${r}% fill=url(#bar)  width=${width}% />
      <text part=percent x=2 y=73% >${width}%</text>
    </svg>`
        }
      })
    </script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search