[SalesForce] Controller method doesn’t rerender pageBlock

My aim is showing the pageBlock named iconGallery, when the user click on the commandLink "Show Gallery". If I put the "loadImage" method's code inside Constructor, everything goes perfect. So I wonder if the problem is between the Controller and VF page.

VF page:

<apex:page id="NewAchievement" controller="NewAchievement_Controller">

      <!-- Import Component -->
            <c:loadingSpinner />

      <!-- Page Header -->
      <apex:sectionHeader title="Achievement Edit" subtitle="New Achievement"/>

      <!-- Begin Form -->
    <apex:form >

    <apex:actionFunction action="{!loadImages}" name="loadImages" reRender="iconGallery" oncomplete="hideLoadingDialog();" />

    <apex:pageBlock title="Achievement Edit" mode="edit">

        <!-- Button Section -->
        <apex:pageBlockButtons location="top">
          <apex:commandButton value="Save" action="{!save}" />
          <apex:commandButton value="Save & New" action="{!saveNew}" />
          <apex:commandButton value="Cancel" action="{!cancel}" />
        </apex:pageBlockButtons>

        <!-- Fields -->
        <apex:pageBlockSection columns="1" showHeader="true" title="Information">
          <apex:inputField value="{!achievement.Name}" required="true" />
          <apex:inputField value="{!achievement.Category__c}" required="false" />
          <apex:inputField value="{!achievement.Points__c}"  required="true" />
          <apex:inputField value="{!achievement.Validation_Criteria__c}" required="true" style="width: 300px"/>
        </apex:pageBlockSection>

        <!-- Icon Selection -->
        <apex:pageBlockSection title="Select Icon">
          <apex:commandLink value="Show gallery"
                            action="{!loadImages}"
                            reRender="iconGallery"
                            onclick="showLoadingDialog();"
                            oncomplete="hideLoadingDialog();" />

          <apex:image value="https://eu6.salesforce.com/servlet/servlet.FileDownload?file=01558000000UI88" />
        </apex:pageBlockSection>
    </apex:pageBlock>

    <!-- Icon Gallery -->

    <apex:pageBlock title="Icon Gallery" id="iconGallery" rendered="">
                <apex:repeat value="{!allLinks}" var="item">
                    <apex:outputLink value="http://www.google.es">
                        <apex:image onclick="String" value="{!item}" style="padding-right: 10px; padding-bottom: 10px"/>
                    </apex:outputLink>
                </apex:repeat>
    </apex:pageBlock>
  </apex:form>
</apex:page>

Controller:

public class NewAchievement_Controller {

public Achievement__c achievement {get; set;}
public List<Document> allImages {get; set;}
public List<String> allLinks {get; set;}
public Boolean isClicked {get; set;}

public NewAchievement_Controller () {

    allImages = new List<Document>();
    allLinks = new List<String>();
    isClicked = false;
}

public PageReference saveNew() {

    try { 
     insert achievement; 
    } catch(System.DMLException e) {
        ApexPages.addMessages(e);
        return null;
    }   
    return (new ApexPages.StandardController(new Achievement__c())).edit();        
}

public PageReference cancel() {

    return (new ApexPages.StandardController(achievement).view());        
}

public PageReference save() {
    try {
        upsert(achievement);
    } catch(System.DMLException e) {
        ApexPages.addMessages(e);
        return null;
    }
    PageReference redirectSuccess = new ApexPages.StandardController(achievement).view();
    return (redirectSuccess);
}

public PageReference loadImages() {

     //LOAD EXISTING IMAGES (16x16)
    allImages = [SELECT Id FROM Document WHERE FolderId = '00l58000000hBuj'];

    String s = 'https://eu6.salesforce.com/servlet/servlet.FileDownload?file=';

    for(Integer i=0; i < (allImages.size()-106); i++) {

        Document d = allImages.get(i);
        allLinks.add(s + String.valueOf(d.Id));
    }

    isClicked = true;

    return null;
}
}

Thank you so much in advance!

Best Answer

For the controller

Change (for clarity - plus all references to it

public Boolean isClicked {get; set;} to

public Boolean hasImageFetchCompleted {get; private set;}

For the VF page:

...
<!-- Icon Selection -->
<apex:pageBlockSection title="Select Icon">
  <apex:commandLink value="Show gallery"
                    action="{!loadImages}"
                    reRender="iconGallery"
                    status="inProgress" />

   ...
</apex:pageBlockSection>

<!-- Icon Gallery -->
<apex:outputPanel id="iconGallery">
<apex:pageBlock title="Icon Gallery"  rendered="{!hasImageFetchCompleted}">
            <apex:repeat value="{!allLinks}" var="item">
                <apex:outputLink value="http://www.google.es">
                    <apex:image onclick="String" value="{!item}" style="padding-right: 10px; padding-bottom: 10px"/>
                </apex:outputLink>
            </apex:repeat>
</apex:pageBlock>
</apex:outputPanel>

Use an apex:actionStatus id="inProgress" ...> to take care of the in progress indicators.

As @TugceSirin stated, you have to wrap the portion of the page that is conditionally visible in a DOM element that is present on page load and stays present, the rerender is to that element (the outputPanel) and the conditional rendering within the output panel will make the images appear once the commandButton's actionMethod loadImages returns.

You should also revisit your controller and remove the hardcoded folder ID (querying for it instead using some custom setting or other sobject value). The constant 106 should be a variable name with some meaningful value so the next person who looks at this knows why 106 is used

Related Topic