I'm using an ion-icon
in my app and I'd like to be able to change some attributes within the svg dynamically. Specifically, I'm using the following battery icon and I want to change the percentage of its fill:
<ion-icon name="battery-full-outline"></ion-icon>
The attribute I'm interested in is the width
attribute in the second of the two <rect>
elements within the SVG. Using my browser tools, I've found the generated HTML to be the following:
<ion-icon _ngcontent-amc-c135="" name="battery-full-outline" ng-reflect-name="battery-full-outline" role="img" aria-label="battery full outline">
#shadow-root (open)
<div >
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0
512 512">
<title>Battery Full</title>
<rect x="32" y="144" width="400" height="224" rx="45.7" ry="45.7" stroke-linecap="square" stroke-miterlimit="10" ></rect>
<rect x="85.69" y="198.93" width="292.63" height="114.14" rx="4" ry="4" stroke-linecap="square" stroke-miterlimit="10" ></rect>
<path stroke-linecap="round" stroke-miterlimit="10" d="M480 218.67v74.66" ></path>
</svg>
</div>
</ion-icon>
The problem of course is that these elements are embedded within a shadow DOM, and Ionic icons don't expose any parts that the user can modify. Is there a way in Angular to get around this? I'm wondering if I can place a directive on the ion-icon
component that would use ElementRef
to access the underlying elements (but it seems like there are some things I haven't considered to make this work).
CodePudding user response:
A simplest way to do it can be editing and creating your own icons. Please, check the
CodePudding user response:
This certainly isn't a good practice (and goes against the fundamentals of Angular), but the simplest solution I could find was just to use plain JavaScript document methods to get the width
attribute I was looking for and to set a new value in the shadow DOM element:
const rect = document.querySelector('.my-icon-class').shadowRoot.querySelectorAll('icon-inner svg rect)[1];
const fullWidth = rect.getAttribute('width');
const newWidth = parseFloat(fullWidth) * BATTERY_PERCENTAGE * 0.01;
rect.setAttribute('width', `${newWidth}`);