6

The old approach of using a helper component to display SVG in Lightning now appears to be blocked in Summer 18. What is a bit alarming, though, is that even components marked with API version 40-42 are also seeing it fail in Summer 18.

An example of such a helper component is Strike SVG from Appiphony:

https://github.com/appiphony/Strike-Components/tree/master/aura/strike_svg

In which a custom Renderer creates the SVG element, creates the USE element, and attaches the href to it. In Summer 18 it creates the elements correctly but fails to attach the href to the USE element.

The root cause of this behaviour change would appear to be this commit to LockerService: https://github.com/forcedotcom/aura/commit/495eaccdc3292a6cf2dcd2c2347c0329c06339e0

Now it also happens to be the case that we're being encouraged to use lightning:icon instead. And I do see that in Summer 18 there is a new src attribute even available for custom SVG paths. That's all pretty cool. But there are certain SLDS blueprints I cannot reproduce using lightning:icon.

One example is the advanced Data Table. Due to some places where lightning:dataTable is still not flexible enough for our needs, I have written a component that constructs the table manually and was trying to add the nifty sort UI where you hover over the column header and see an arrow appear to indicate that clicking there will sort it. See here: https://www.lightningdesignsystem.com/components/data-tables/ (click Advanced under Variants).

The following snippet is included in that blueprint markup to render said arrow:

      <div class="slds-icon_container">
        <svg class="slds-icon slds-icon_x-small slds-icon-text-default slds-is-sortable__icon" aria-hidden="true">
          <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#arrowdown" xmlns:xlink="http://www.w3.org/1999/xlink" />
        </svg>
      </div>

Note that it's asking us to put the class slds-is-sortable__icon on the SVG tag itself. Suppose I attempt to implement this using lightning:icon. So I try the following:

<lightning:icon iconName="utility:arrowdown" class="slds-is-sortable__icon"
                    size="x-small" />

When I render that in a Lightning component and Inspect Element this is what I get:

<lightning-icon class="slds-is-sortable__icon slds-icon-utility-arrowdown slds-icon_container" data-aura-rendered-by="87:0">
    <lightning-primitive-icon lightning-primitive-icon_primitive-icon="">
        <svg focusable="false" data-key="arrowdown" aria-hidden="true" class="slds-icon slds-icon-text-default slds-icon_x-small" lightning-primitive-icon_primitive-icon="">
            <use xlink:href="/_slds/icons/utility-sprite/svg/symbols.svg?cache=9.8.0#arrowdown" lightning-primitive-icon_primitive-icon=""/>
        </svg>
    </lightning-primitive-icon>
</lightning-icon>

Note that the slds-is-sortable__icon class was applied to the wrapper instead of the SVG itself. And indeed, the outcome is not the desired one: Because the sortable class is placed on an outer element instead of the correct one, the styles cascade incorrectly. Since lightning:icon does not have any way to add custom classes directly to the SVG tag, the blueprint is impossible to reproduce in a Summer 18 Lightning Component. In Spring 18 my workaround was to import Strike SVG and use that to place the class on the SVG tag, but now that's unusable.

Any thoughts?

  • Instead of lightning:icon if you use lightning:buttonIcon, it has an attribute iconClass where we can specify the class name for SVG. Not sure if that solves the purpose, example: <lightning:buttonIcon iconName="utility:arrowdown" variant="bare" alternativeText="Settings" iconClass="svg-class" class="button-container-class"/> – Raul May 11 '18 at 20:35
  • @Raul You might add that as a viable answer. I did check, and iconClass does indeed get attached directly to the svg. – sfdcfox May 11 '18 at 20:41
  • @charles-t Locker Service team has been notified of this issue with SVG elements using href attribute in Summer 18. We are working on a resolution. If you file a customer case, please reference this investigation W-4981475 – Ravi Jayaramappa May 14 '18 at 18:17
  • @RaviJayaramappa Thank you, much appreciated! Certainly if there will be an intended behaviour change it should be disclosed in the Release Notes, but it should not retroactively be affecting older API versions without an official announcement. – Charles T May 14 '18 at 18:27
  • @RaviJayaramappa was a resolution found in time for the release? – Charles T Jun 12 '18 at 14:14
2

You'll want to ask about this over on the Collaboration groups at success.salesforce.com, as well as perhaps logging a bug with Technical Support. I'm not sure how far we'll get with it, but it doesn't hurt to get started on it before the public release.

In the meantime, you can still work around the problem, it's just non-trivial. Using my progressRing example, the source you've linked implies we can still use path, rect, and other SVG elements, so you could copy-paste the actual paths from the resources and convert them to code similar to my design.

Obviously, this will limit your ability to keep up to date with the current SLDS, although I suspect another alternative would be to download the public assets (e.g. "apexpages/slds/latest/assets/icons/utility-sprite/svg/symbols.svg"), parse it manually using a DocumentFragment, find the appropriate path, and then attach it as a child of the SVG tag. I'm going to experiment with this, but please feel free to let me know if you get it working.

Finally, as an absolute fallback, consider using the PNG-based images instead, which you may need to download as a static resource. I hate recommending this, because it's terribly inflexible, but it would at least be a temporary stopgap until you can come up with a more permanent solution.

  • My temporary stopgap is, I just decided to use Unicode up/down arrows and build them in a way that works on both Spring/Summer. I will definitely consider posting it in more places, however a little birdie once told me that the Locker Service team monitors the locker-service tag on here so I figured it is worth a try. – Charles T May 12 '18 at 4:01
  • Overall, now that there are more base Lightning Components available, it would be really grand if the official SLDS site could offer their blueprint markup in a format that is usable in Lightning Components themselves. – Charles T May 12 '18 at 4:03
  • @CharlesT Yes, Salesforce devs and PMs are known to frequent the forum, but you probably don't want to make this your only channel of communication. Still, I agree, it'd be useful for the SLDS site to have that info. – sfdcfox May 12 '18 at 4:17
1

Until iconClass is added to lightning:icon, use lightning:buttonIcon as it provides the closest user experience and has an attribute iconClass where we can specify the class name for SVG.

Not really sure if this solves the purpose in your situation, example:

<lightning:buttonIcon iconName="utility:arrowdown" variant="bare" 
    alternativeText="Settings" iconClass="svg-class" class="button-container-class"/>~

generates output as (svg-class is applied to SVG tag):

enter image description here

  • Thanks, that might be viable. I will have to see whether it behaves like the blueprint in this scenario. – Charles T May 12 '18 at 4:01
  • I gave it a try but it appears that because the container is a button, it produces other unwanted outcomes compared to the blueprint. – Charles T May 18 '18 at 17:27
0

Salesforce did resolve this before Summer '18 rolled out. If any Lightning Components are failing to display SVG that worked before Summer '18 please check for other possible issues such as URLs that are no longer valid.

  • SVG's USE is now available? – sfdcfox Jun 15 '18 at 14:53
  • You still have to take the "component with renderer" workaround. However during Summer '18 previews a change to LockerService prevented this from working. The issue was resolved by the time Summer '18 went GA. – Charles T Jun 16 '18 at 2:50
  • Oh, okay, that makes sense. Glad they fixed that before it went GA, at least. – sfdcfox Jun 16 '18 at 2:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.