You need to sign in to do that
Don't have an account?
Can't use rerender and onclick together on commandlink/commandbutton?
I've got a visualforce page that displays a list of child items with links that allow them to be deleted. I'm trying to refresh the list upon deletion with AJAX, but have run into a stumbling block. It appears that if I use an onclick attribute and rerender attribute together on the commandlink doing the deletion, it doesn't work. I'm using the onclick attribute to popup a confirmation box and the rerender to attempt the AJAX refresh. If I drop the onclick, it works as expected (with no confirmation). If I drop the rerender, if works as expected (with a full page refresh). If I use both, it pops up the confirmation box, but then doesn't even call the controller (nothing shows up in the system log).
It appears to exhibit the same behavior if I substitute a commandbutton for the commandlink.
I've reproduced this with the simple code here (though the real code is returning a list of actual SObjects)...
Page:
<apex:page controller="TestController"> <apex:pageMessages /> <apex:form > <apex:pageBlock title="Test" id="ListBlock"> <apex:pageBlockTable value="{!Records}" var="i"> <apex:column headerValue="Action"> <apex:commandLink action="{!delrec}" immediate="true" onclick="return confirm('Are you sure?')" rerender="ListBlock" >Del <apex:param name="delid" value="{!i}"/> </apex:commandLink> </apex:column> <apex:column headerValue="ID" > <apex:outputtext value="{!i}" /> </apex:column> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>
Controller:
public with sharing class TestController { Map<string,Integer> x; public TestController() { x = new Map<string,Integer>(); x.put('1',1); x.put('2',2); x.put('3',3); } public List<Integer> getRecords() { return x.values(); } public PageReference delRec() { x.remove(ApexPages.currentPage().getParameters().get('delid')); return null; } }
Any ideas?
Thanks!
- Dov
Try this
<apex:page controller="TestController">
<head>
<script type='text/javascript'>
function confirmMessage(recId)
{
confirm('Are you sure');
document.getElementById('{!$Component.formID.delRecID}').value = recId;
delRecAction();
}
</script>
</head>
<apex:pageMessages />
<apex:form id="formID">
<apex:actionFunction name="delRecAction" action="{!delrec}" rerender="ListBlock"/>
<apex:inputHidden value="{!delRecVal}" id="delRecID"></apex:inputHidden>
<apex:pageBlock title="Test" id="ListBlock">
<apex:pageBlockTable value="{!Records}" var="i">
<apex:column headerValue="Action">
<apex:commandLink onclick="return confirmMessage('{!i}')" rerender="ListBlock" >Del
<apex:param name="delid" value="{!i}"/>
</apex:commandLink>
</apex:column>
<apex:column headerValue="ID" >
<apex:outputtext value="{!i}" />
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
In Apex class , add variable delRecVal
public with sharing class TestController {
Map<string,Integer> x;
public String delRecVal {get; set;}
public TestController() {
delRecVal = null;
x = new Map<string,Integer>();
x.put('1',1);
x.put('2',2);
x.put('3',3);
}
public List<Integer> getRecords() {
return x.values();
}
public PageReference delRec() {
x.remove(delRecVal);
return null;
}
}
If you face any issues let me know.
All Answers
Try this
<apex:page controller="TestController">
<head>
<script type='text/javascript'>
function confirmMessage(recId)
{
confirm('Are you sure');
document.getElementById('{!$Component.formID.delRecID}').value = recId;
delRecAction();
}
</script>
</head>
<apex:pageMessages />
<apex:form id="formID">
<apex:actionFunction name="delRecAction" action="{!delrec}" rerender="ListBlock"/>
<apex:inputHidden value="{!delRecVal}" id="delRecID"></apex:inputHidden>
<apex:pageBlock title="Test" id="ListBlock">
<apex:pageBlockTable value="{!Records}" var="i">
<apex:column headerValue="Action">
<apex:commandLink onclick="return confirmMessage('{!i}')" rerender="ListBlock" >Del
<apex:param name="delid" value="{!i}"/>
</apex:commandLink>
</apex:column>
<apex:column headerValue="ID" >
<apex:outputtext value="{!i}" />
</apex:column>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:form>
</apex:page>
In Apex class , add variable delRecVal
public with sharing class TestController {
Map<string,Integer> x;
public String delRecVal {get; set;}
public TestController() {
delRecVal = null;
x = new Map<string,Integer>();
x.put('1',1);
x.put('2',2);
x.put('3',3);
}
public List<Integer> getRecords() {
return x.values();
}
public PageReference delRec() {
x.remove(delRecVal);
return null;
}
}
If you face any issues let me know.
That worked great. Thanks!
I just had to tweak the javascript a little so that "cancel" worked:
Is there some reason the original code doesn't work? Is it a bug or some nuance that I'm missing?
In any case, thanks for the help!
- Dov
Yeah there's a nuance here that's not obvious. Actions that fire off AJAX commands have to do so via javascript calls. When you add events like onclick to insert your own javascript, that stuff gets prepended before the AJAX call. So if you've got a confirm statement with a return in it, you're really returning from your javascript statement before it gets to submit anything.
The solution is only doing the return if someone clicks cancel, so:
<apex:commandButton onclick="if (!confirm('are you sure?')) return;" rerender="theForm"/>
That simple change worked great and avoids the somewhat messier javascript needed otherwise. Thanks!
-Dov