[SalesForce] Lightning design system – SVG disappears after rerender

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?

Best Answer

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>

Related Topic