3

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?

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>

  • 1
    Please provide reason when you negatively vote on an answer and feel free to reach out to me – Mohith Shrivastava Aug 4 '16 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 – Vladyslav K Aug 4 '16 at 17:35
  • You can create a helper method with the approach and keep it generic – Mohith Shrivastava Aug 4 '16 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 '16 at 9:58
4

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

1

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>

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.