Unleash the power of SVG in LWC
Using vector-based images in Salesforce web applications has always been a pain. Visualforce never really provided native support and although SVGs have been around long before the rise of Lightning Components, we were still dependent on a non-intuitive, non-performant and non-scaleable wrapper component.
Luckily, Lightning Web Components provide FULL support! This opens up a range of easy to use, fast-loading, beautiful images for you to utilize in Salesforce applications and mobile solutions.
So how can you achieve this? You can just get SVG code and mash it in your code, like this (overly simple) example:
<svg viewBox="0 0 5 5" aria-hidden="true">
<circle cx="50%" cy="50%" r="1.875"></circle>
</svg>
But how do we organize our code, and how do we make sure that we don’t get bloated web components because of unreadable SVG code?
A very efficient way to approach this, is through a so-called SVG-provider component. One component that hosts all large SVG’s that might appear on multiple locations in your application.
As you might know, a web component can contain multiple html-files. This means that you can actually define an html instance per SVG image!
Let’s say you want to use typical Salesforce images (like these), then go ahead, and create a LWC structure like below. It contains a javascript file, which will take care of some routing logic to the right SVG file, a meta file and two html files, which represents the illustrations.
Let’s take a look at svgGoneFishing.html
. It’s quite lengthy, so here is a (pardon me) a screenshot:
Note that this is code that is directly copied over from Salesforce’s Lighting Design system. It requires quite some skill and madness to write this type of code from scratch!
Let’s take a look at the javascript over here:
import { LightningElement, api } from 'lwc';
import svgShowEmpty from './svgShowEmpty.html';
import svgGoneFishing from './svgGoneFishing.html';
export default class SvgProvider extends LightningElement {
@api message;
@api svgname;
renderHtml = {
'showempty' : svgShowEmpty,
'gonefishing' : svgGoneFishing
};
render() {
if(this.renderHtml[this.svgname]) {
return this.renderHtml[this.svgname];
} else {
return svgShowEmpty;
}
}
}
It is amazing how compact code can be right?
What you see above is the logic that is responsible for loading the right html file. The svgName property dictates what SVG should appear onscreen, and that happens during the render lifecycle hook. Why the render? Because we want the appropriate html actually getting loaded in the Dom before any other logic fires up.
Also, because we use the @api annotation to the property, the svg will always be updated whenever this property changes. How dynamic!
Including this component is how you would include any other component, and is available for both lightning web components:
<c-svg-provider svgname=”goneFishing"></c-svg-provider>
And lightning components:
<c:svgProvider svgName="goneFishing" />
Few other arguments to use SVG whenever you can:
- SVG is vector based, so scaling is extremely efficient and fast!
- No need to retrieve these images from the server through documents or static resources!
- No dependency on externally hosted images through image url’s!
- SVG’s can be animated!
I would suggest you try this out for yourself, and start spicing up your component with flashy SVGs!
also, for those not getting enough of SVG’s, check how to incorporate slots into them!
Good luck!