4

I am building data table, here is html code from browser before rerendering table. I use actionFunction with rerender attribute. The problem is that svg disappears after rerendering.

Before rerender:

<th aria-label="Account Name" class="slds-is-sortable slds-is-resizable" scope="col">
    <a class="slds-th__action slds-text-link--reset" href="javascript:void(0);">
        <span class="slds-assistive-text">Sort</span>
        <span class="slds-truncate" title="Account Name">Account Name</span>
        <div class="slds-icon__container">
            <svg aria-hidden="true" class="slds-icon slds-icon--x-small slds-icon-text-default slds-is-sortable__icon">
                <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/resource/1454076265000/SLDS01201/assets/icons/utility-sprite/svg/symbols.svg#arrowdown"></use>
            </svg>
        </div>
        <span aria-atomic="true" aria-live="assertive" class="slds-assistive-text"></span>
    </a>
</th>

After rerender:

<th aria-label="Account Name" class="slds-is-sortable slds-is-resizable" scope="col">
    <a class="slds-th__action slds-text-link--reset" href="javascript:void(0);">
        <span class="slds-assistive-text">Sort</span>
        <span class="slds-truncate" title="Account Name">Account Name</span>
    </a>
    <div class="slds-icon__container"></div>
    <span aria-atomic="true" aria-live="assertive" class="slds-assistive-text"></span>
</th>

How to solve this? The response of request for rerender in Chrome dev tools looks like this:

<html lang="en_US" xmlns="http://www.w3.org/1999/xhtml">

Maybe the issue is that xmlns="http://www.w3.org/2000/svg" is missing?

3 Answers 3

5

Its a known bug in SFDC Visualforce page .I have used a jquery approach with action function to manually write the DOM .You can use Oncomplete event and custom write the DOM to replace

The Script would look like below

  <script>
        var j$ = jQuery.noConflict();
          function renderSVG(){
            var imageURL = '{!URLFOR($Resource.SLDS0102, 'assets/icons/standard-sprite/svg/symbols.svg#user')}';
            var SVG = j$('<svg/>', {
               class: 'slds-icon slds-icon--large slds-icon-standard-user',
            });

            var SVGUse = j$('<use/>');
            SVGUse.attr('xlink:href',imageURL);
            j$('#Icon').prepend(SVG.append(SVGUse));
            j$('#Icon' ).html(j$('#Icon').html());
          }
        </script>

The complete code is as below Showing an Action Function calling an apex method and then OnComplete Jquery call to render back the SVG .Also note you can write a generic function to handle this if you have multiple ajax calls

<apex:page controller="SVGRerendering" standardStylesheets="false" showHeader="false" id="thepage">
<html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <head>
        <apex:stylesheet value="{!URLFOR($Resource.SLDS0102, 'assets/styles/salesforce-lightning-design-system-vf.css')}" />
         <apex:includeScript value="//code.jquery.com/jquery-2.1.4.min.js" />
    </head>
    <body>
        <apex:form id="frm">
            <apex:outputPanel id="SVGIcon" layout="block">
            <div class="slds" id="Icon">
                <svg aria-hidden="true" class="slds-icon slds-icon--large slds-icon-standard-user">
                    <use xlink:href="{!URLFOR($Resource.SLDS0102, 'assets/icons/standard-sprite/svg/symbols.svg#user')}" />
                </svg>
                <apex:outputText value="{!helloUser}"></apex:outputText><br/><br/>
                <apex:commandButton value="Rerender Form" styleClass="slds-button slds-button--neutral" reRender="frm" action="{!HelloWorld}" oncomplete="renderSVG();"/>
            </div>
            </apex:outputPanel>
        </apex:form>
        <script>
        var j$ = jQuery.noConflict();
          function renderSVG(){
            var imageURL = '{!URLFOR($Resource.SLDS0102, 'assets/icons/standard-sprite/svg/symbols.svg#user')}';
            var SVG = j$('<svg/>', {
               class: 'slds-icon slds-icon--large slds-icon-standard-user',
            });

            var SVGUse = j$('<use/>');
            SVGUse.attr('xlink:href',imageURL);
            j$('#Icon').prepend(SVG.append(SVGUse));
            j$('#Icon' ).html(j$('#Icon').html());
          }
        </script>
    </body>
</html>

4
  • 1
    Please provide reason when you negatively vote on an answer and feel free to reach out to me Aug 4, 2016 at 17:24
  • I didn't vote down your answer, but the solution you offer seems to be effective if I have few svg, but I can't produce so much Javascript for every svg Aug 4, 2016 at 17:35
  • You can create a helper method with the approach and keep it generic Aug 4, 2016 at 18:20
  • Not my downvote either, but a code dump is a lot less useful without the explanation piece. Can you expand your explanation of why what you posted resolves the issue?
    – Adrian Larson
    Aug 5, 2016 at 9:58
4

Just set your apex:page attribute docType="html-5.0" and this will fix the rerender SVG bug

0
2

I was able to overcome the problem of SVG images disappearing when their containing <apex:*> tag is re-rendered:

  1. Add docType="html-5.0" attribute to the <apex:page> tag;
  2. Put the xmlns="..." and xmlns:xlink="..." attributes directly on the <use ...> tag, together with xlink:href="..." value for the SVG icon.

Please see the example below:

<apex:page standardController="Account" extensions="ExampleController" action="{!doInit}"
    lightningStylesheets="true" docType="html-5.0">
....
<apex:outputPanel id="rerenderedPanel">
<apex:commandLink action="{!addLine}" rerender="rerenderedPanel" status="panelStatus" title="Add Line"
        styleClass="slds-button slds-button_icon slds-button_icon-border-filled">
    <apex:outputPanel>
    <svg class="slds-button__icon slds-button__icon_hint" aria-hidden="true">
        <!-- !!!!!!!!!!!!!!! -->
        <use xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
                xlink:href="{!URLFOR($Asset.SLDS,
                    '/assets/icons/action-sprite/svg/symbols.svg#Add')}"></use>
        <!-- !!!!!!!!!!!!!!! -->
    </svg>
    <span class="slds-assistive-text">Add Line</span>
    </apex:outputPanel>
</apex:commandLink>
</apex:outputPanel>
....
</apex:page>
1

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .