function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kenji775Kenji775 

pageBlockTable won't rerender

Hey all,

I feel dumb even posting this, becuase I'm sure it's just a typo or some goofy thing, but I feel like I've wasted enough time tracking it down. Time to let the big guns help me out ;)

 

Pretty simple thing. I have a pageBlockTable. One of the links in it, lets me delete that row. After the row is deleted the table should be rerendered so you can see that it has been removed. Currently the record DOES get deleted, but the table is not rerendered. I tried putting it in an output panel and no luck there. I was wondering if maybe the table is reloading before the record is actually deleteed, causing a 'race' condition type of situation? Anyway, below is the code. Feel free to point out what I am doing wrong, and then laugh at me for being such a newb :P

Page (unneccary crap removed)

<apex:form id="form">
    <apex:actionFunction action="{!deleteFile}" name="removeAttachment" reRender="attachmentsTable" status="working" >
        <apex:param name="aId" value="" />
    </apex:actionFunction>
	
    <apex:actionstatus id="working">
		Deleting....
	</apex:actionstatus>
    
    
        <apex:pageBlock title="Existing Attachments" rendered="{!showExisting}" id="attachmentsTable">
            <apex:pageBlockTable value="{!attachments}" var="attachment">
                <apex:column headerValue="Action">
                    <apex:outputLink value="{!URLFOR($Action.Attachment.Download, attachment.Id)}" target="_blank">View</apex:outputLink>
                    |
                    <apex:outputText> <a id="{!attachment.id}" class="deleteLink">Del</a> </apex:outputText>
                </apex:column>
                <apex:column value="{!attachment.Name}"/>
                <apex:column value="{!attachment.Description}"/>
            </apex:pageBlockTable>
        </apex:pageBlock>
 
</apex:form>

 controller

 

   public static void deleteFile()
    {
        string attachmentId = Apexpages.currentPage().getParameters().get('aId');
        Attachment thisAttachment = new Attachment(id=attachmentId);
        delete thisAttachment;        
    }

 

Best Answer chosen by Admin (Salesforce Developers) 
Kevin SwiggumKevin Swiggum

A couple of other things to try.

 

Pull out the reference to the ActionStatus just to make sure that's not getting in the way (is your action status message showing up?)

 

Pull the table out of the apex:form...just have the form around the action function. 

 

I'll sometimes stick a datetime variable inside the re-rendered section just to tell me if it's actually re-rendering.

All Answers

michaelforcemichaelforce

reRender on the actionFuntion is supposed to work when the method returns... but your method is void, doesn't return anything.  This might have something to do with it... you could try returning a null PageReference from that method instead and see if it changes anything.

Kenji775Kenji775

Nice suggestion, makes sense in theory. I tried changing my method to the following, but alas no success.

   public static PageReference deleteFile()
    {
        string attachmentId = Apexpages.currentPage().getParameters().get('aId');
        Attachment thisAttachment = new Attachment(id=attachmentId);
        delete thisAttachment;     
         return null;
    }

  as well as 

 

   public static PageReference deleteFile()
    {
        string attachmentId = Apexpages.currentPage().getParameters().get('aId');
        Attachment thisAttachment = new Attachment(id=attachmentId);
        delete thisAttachment;     
         return ApexPages.currentPage();
    }

 

 

Kevin SwiggumKevin Swiggum

I might be missing something. I can't see where you're calling your action function from the delete link. I usually put in a javascript call, but is there another way to do it?

 

I also noticed your use of actionStatus and I'm wondering if something is missing there. I usually use either startText/stopText attribute or an apex:facet name="start". However, I may just not know that the way you're doing it is a valid shortcut....thought I'd mention it either way. 

 

One other thought...how are you populating the attachments list? I didn't see anything in the delete link method that would force the attachements to re-pull the updated list. The constructor for the controller doesn't get called again since it's not a full page reload. 

Kenji775Kenji775

All valid questions. I left out some of that junk cause I wanted to keep it simple, but basically what happens is the delete link has a bound action (courtesy of jQuery). Click the link causes it to display a dialog box that asks if you are sure. If you say yes, then the action function gets called. 

As for the population of the attachments list, I though since it was a rerender and its variable is the attachments list, the method getAttachments would be invoked again and now that list would be minus the attachment that was just deleted. There is a method called getAttachments that looks like this.

   // retrieve the existing attachments
    public List<Attachment> getAttachments()
    {
        if (attachments==null)
        {
            attachments=[select Id, ParentId, Name, Description from Attachment where parentId=:sobjId];
        }
        
        return attachments;
    }

 I also tried hard coding a call to getAttachments within my delete function, but it didn't seem to make a difference. You might be onto something though. The list may be rerendering, but the list is still the same. Any ideas for an easy test to see if the table is actually getting redrawn?

 

Also, other code that I mentioned.



Registering the action of the delete link

          $('.deleteLink').click(function() {
                 id = $(this).attr('id');
       
                 $('#dialog-confirm').dialog('open');
                 return false;
           })

 

Creating the dialog that lets users confirm they want to delete the file

            $( ".dialog" ).dialog({
                resizable: false,
                autoOpen:false,
                height:140,
                modal: true,
                buttons: {
                    "Delete File": function() {
                     
                        $( this ).dialog( "close" );
                        removeAttachment(id);
                        
                    },
                    Cancel: function() {
                        $( this ).dialog( "close" );
                    }
                }
            });

 
the div used for the dialog box

<div id="dialog-confirm" class="dialog" title="Delete Attachment?">
    <p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>Are you sure you want to delete this attachment?</p>
</div>    

 

 

 

 

michaelforcemichaelforce

Ahh, yeah... Kevin made a good point... looks like you need to refresh the "attachments" variable after you do the delete (or during the get) because it probably still holds the deleted record.

Kevin SwiggumKevin Swiggum

Try setting the attachments variable back to null after doing the delete. Right  now, you have an if (attachments == null) condition before it re-queries....since attachments is still populated, it won't requery.

Kenji775Kenji775

I think you guys are probably right, but my tweaking still isn't quite working. I changed my getter to

   // retrieve the existing attachments
    public List<Attachment> getAttachments()
    {
        attachments=[select Id, ParentId, Name, Description from Attachment where parentId=:sobjId];
        return attachments;
    }

 and my deleteFile method to

   public  PageReference deleteFile()
    {
        string attachmentId = Apexpages.currentPage().getParameters().get('aId');
        Attachment thisAttachment = new Attachment(id=attachmentId);
        delete thisAttachment;     
         getAttachments();
         return ApexPages.currentPage();
    }

 

 

 Still no joy. :(

Kevin SwiggumKevin Swiggum

Are you seeing any Javascript errors?

 

Kenji775Kenji775

No, non reported in the error console. 

Also, just to be super sure, I changed my deletefunction to both nullify the attachments list, and reget it. I also removed that null checking condition.

 

   public  PageReference deleteFile()
    {
        string attachmentId = Apexpages.currentPage().getParameters().get('aId');
        Attachment thisAttachment = new Attachment(id=attachmentId);
        delete thisAttachment;
        Attachments = null;     
        Attachments = getAttachments();
        return ApexPages.currentPage();
    }

 

michaelforcemichaelforce

Just to experiment... try returning a null pageReference from your delete method and totally remove the "reRender" from your actionFunction.  This is supposed to refresh the entire page... if it does that might be a good fix for you, or at least prove that the function is running as expected.

Kevin SwiggumKevin Swiggum

A couple of other things to try.

 

Pull out the reference to the ActionStatus just to make sure that's not getting in the way (is your action status message showing up?)

 

Pull the table out of the apex:form...just have the form around the action function. 

 

I'll sometimes stick a datetime variable inside the re-rendered section just to tell me if it's actually re-rendering.

This was selected as the best answer
Kenji775Kenji775

It works now. I think the change that did it was making it return null instead of the current page reference. Maybe the current page reference had the list in the viewstate or something? Hell if I know. Either way I'm glad it works. Thanks guys!

Shashikant SharmaShashikant Sharma

{!showExisting} is this false first time when page loads, in case yes then

 

just add a OutputPanel above the table and give it a id="opTable" and rerender it.

 

Why I am suggesting it is that if any thing is not rendered first time can not be rerendered later also.

 

Please let me know if your case is such or not.

Developer.mikie.Apex.StudentDeveloper.mikie.Apex.Student

Kenji, can you please post finished code?