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
forcewithuforcewithu 

Can't get radio buttons to rerender

I’m having a problem getting my Visualforce radio buttons to work as designed in a wizard.
 
The original design was to have a table with multiple rows where the first column was a radio button and the subsequent columns were various fields associated with a particular contact.  The idea was that someone could use the information displayed on each row to select a contact for use on subsequent pages.  I discovered that it wasn’t really possible to split up the radio buttons for use on different table rows using Visualforce.
 
So, I went to a backup plan to display a group of radio buttons along with the name of the associated contact.  Below the group of buttons is a table to display the other information for the selected contact.  The desired behavior is to have the contact’s information automatically display when selecting the radio button.  I can get it to display when using a Select button (CommandButton), but I can’t seem to get the radio buttons to fire an event that I can use to re-render the table.
 
I’ve gone through multiple designs and am currently attempting a hybrid of one suggested by an instructor after the original one didn’t work.  Because selectRadio doesn’t have a rerender attribute, he suggested that I use actionSupport to add that functionality.
 
Here’s the Visualforce code for the radio buttons as it currently stands:
 
Code:
<apex:pageBlockSection title="Select Contact">
     <apex:selectRadio id="Contact_Selection" value="{!ContactAssignment}" layout="pageDirection" onchange="{!ContactInfo}" immediate="true" required="true">
          <apex:selectOptions value="{!ContactList}">
          <apex:actionSupport event="onchange" action="{!getContactInfo}" reRender=”out" status="status" immediate="true"/>
          </apex:selectOptions>
     </apex:selectRadio>
     <p/>
     <apex:commandButton value="Select" action="{!getContactInfo}" rerender="out" status="status"/>
</apex:pageBlockSection>

 
The code shown includes the Select commandButton that works well.  But I’ve tried every event I could think of in both the actionSupport and selectRadio tags: onChange, onClick, onSelect, you name it.  None of them will fire the getContactInfo action to rerender the page.  If you select a radio button and do NOT click on the Select button, it still captures the information for further processing.  I just can’t get it to rerender the outpanel so the user can see the additional contact information.
 
All I need to do is find a way to get the selection of a radio button to execute getContactInfo the way the Select button does.
jwetzlerjwetzler
why are you using immediate="true"?

Try taking that out.
forcewithuforcewithu
I put that in when it wasn't working without it.  I've removed immediate="true" in both places.  Still doesn't work.
jwetzlerjwetzler
Do you mind posting your page and controller code?
forcewithuforcewithu
Code:
<apex:page controller="PASSPORT_Opp_Implementation_Controller" tabStyle="Opportunity">
        <apex:sectionHeader title="Passport Implementation" subtitle="Step 3 of 5"/>

        <apex:form id="theForm">
                <apex:pageBlock >
                         <apex:pageBlockButtons >
                                <apex:commandButton action="{!selectOpps}" value="< Previous"/>
                                <apex:commandButton action="{!contactDetail}" value="Next >"/>
                                <apex:commandButton action="{!cancel}" value="Cancel"/>
                        </apex:pageBlockButtons>
                <table cellPadding="1" border="0" width="800px">
                    <tr>
                        <td width="15%"><b><u>Account Name:</u></b></td>
                        <td width="40%">{!opportunity.account.name}</td>
                        <td width="*"><b><u>Account Mailing Address:</u></b></td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>{!opportunity.account.MailingAddressLine1__c}</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>{!opportunity.account.MailingAddressLine2__c}</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>{!opportunity.account.MailingAddressLine3__c}</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td></td>
                        <td>{!opportunity.account.mailingaddresscity__c}, {!opportunity.account.mailingaddressstate__c}  {!opportunity.account.mailingaddresszip__c}</td>
                    </tr>
                </table>
        <apex:outputPanel id="out">
        <apex:pageBlock >
            <apex:pageblockSection title="Primary Contact Selection">
                <apex:actionstatus id="status" startText="selecting...">
                        <apex:facet name="stop">
                                <apex:outputPanel >
                                        <p>You have selected:</p>
                <apex:dataTable value="{!contact}" var="aContact" cellPadding="8" border="1" width="600px">
                            <apex:column ><apex:facet name="header" ><b>Contact Name</b></apex:facet>{!aContact.Name}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Title</b></apex:facet>{!aContact.Title}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Phone</b></apex:facet>{!aContact.Phone}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Email</b></apex:facet>{!aContact.Email}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>City</b></apex:facet>{!aContact.MailingCity}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>State</b></apex:facet>{!aContact.MailingState}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Zip</b></apex:facet>{!aContact.MailingPostalCode}</apex:column>
                    </apex:dataTable>
                                </apex:outputPanel>
                        </apex:facet>
                </apex:actionstatus>
            </apex:pageBlockSection>
        </apex:pageBlock>
        </apex:outputPanel>
        
                        <apex:pageBlockSection title="Select Contact">
                            <apex:selectRadio id="Contact_Selection" value="{!ContactAssignment}" layout="pageDirection" onchange="{!ContactInfo}" required="true">
                                    <apex:selectOptions value="{!ContactList}">
                                        <apex:actionSupport event="onchange" action="{!getContactInfo}" reRender="out" status="status"/>
                                    </apex:selectOptions>
                             </apex:selectRadio><p/>
                             <apex:commandButton value="Select" action="{!getContactInfo}" rerender="out" status="status"/>
                              <apex:outputLabel value="One contact must be selected for an implementation request." rendered="{!RenderContactReqdMsg}" style="font-weight: bold; color: #C00; text-align: center;"/>
                        <apex:message for="Contact_Selection" title="Contact Selection is required"/>
                        </apex:pageBlockSection>
                </apex:pageBlock>
       </apex:form>
        <apex:pageBlock >
                        <apex:pageBlockSection title="Originating Opportunity Information">
                                <apex:outputField id="opportunityName" value="{!opportunity.name}"/>
                                <apex:outputField id="opportunityOwner" value="{!opportunity.ownerid}"/>
                                <apex:outputField id="opportunityProjectedAnnualRevenue__c" value="{!opportunity.ProjectedAnnualRevenue__c}"/>
                                <apex:outputField id="opportunityStage" value="{!opportunity.stagename}"/>
                                <apex:outputField id="opportunityCloseDate" value="{!opportunity.closedate}"/>
                        </apex:pageBlockSection>
            <apex:pageblockSection title="Additional Opportunities Linked">
                                <apex:outputPanel >
                <apex:dataTable value="{!CheckOpportunities}" var="check" cellPadding="8" border="1" width="600px">-->
                            <apex:column ><apex:facet name="header" ><b>Opportunity Name</b></apex:facet>{!check.opportunity.name}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Product</b></apex:facet>{!check.opportunity.Product__c}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Projected Annual Revenue</b></apex:facet><apex:outputField value="{!check.opportunity.ProjectedAnnualRevenue__c}"/></apex:column>
                            <apex:column ><apex:facet name="header" ><b>Owner Name</b></apex:facet>{!check.opportunity.owner.name}</apex:column>
                            <apex:column ><apex:facet name="header" ><b>Close Date</b></apex:facet>{!month(check.opportunity.closedate)}/{!day(check.opportunity.closedate)}/{!year(check.opportunity.closedate)}</apex:column>
                    </apex:dataTable>
                                </apex:outputPanel>
            </apex:pageBlockSection>
        </apex:pageBlock>
</apex:page>


 
:smileysad: I was afraid you'd ask that.  (sigh) I'm so embarrased by this code.  I didn't even know what Salesforce WAS about 6 weeks ago, so I was really floundering and learning by error as I tried to code something designed by someone else.

Anyway, here's the controller:

Code:
public class PASSPORT_Opp_Implementation_Controller
{


    public Integer getNumberOfOppties() {
        return numberOfOppties;
    }


    public Boolean getRenderAddrReqdMsg() {
        if ((thecontact.mailingstreet==null) || (thecontact.mailingcity==null) || (thecontact.mailingstate==null) ||(thecontact.mailingpostalcode==null))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public Boolean getRenderPhoneReqdMsg() {
        if ((thecontact.phone==null) && (thecontact.homephone==null) && (thecontact.otherphone==null))
        {
            return true;
        }
        else
        {
            return false;
        }
    }



        // These member variables maintain the state of the wizard
        // When users enter data into the wizard, their input is stored
        // in these variables
        Contact theContact;
        Opportunity opportunity;
        PASSPORT_Implementation__c passport_master_record;
        PASSPORT_Implementation_Opportunities__c passport_opportunity_record;
        public String contactassignment = null;
        public String SelectedContactId {get; set;}
        Set<String> link_Opportunities = new Set<String>();
        integer numberOfOppties = 0;

  
        // The next methods return one of each of the member
        // variables. If this is the first time the method is called,
        // it creates an empty record for the variable.


        public Contact getTheContact() 
        {
                theContact = [SELECT Id, Email, Fax, FirstName, HomePhone, LastName, 
                           MailingCity, MailingCountry, MailingPostalCode, MailingState, MailingStreet, 
                           MobilePhone, OtherPhone, Phone, Salutation, Title 
                        FROM Contact WHERE Id=:contactassignment];
        return theContact;
        }

    public string getContactAssignment()
    {
       return contactassignment;
    }
        
    public void setContactAssignment(String contactassignment) { this.contactassignment = contactassignment; }        

    public List<SelectOption> getContactList()
    {
                List<SelectOption> options = new List<SelectOption>();
        for(Contact c : [SELECT Id, Name, LastName FROM Contact WHERE AccountId =:opportunity.accountid
            AND RecordType.Name <> 'STB Intranet Directory Contact'
            ORDER BY LastName]) 
            options.add(new SelectOption(c.Id, c.Name));
        return options;
    }

        public List<Contact> getContact() 
        {
                return [SELECT Id, Email, Fax, Name, MailingStreet, MailingCity, MailingPostalCode, MailingState, Phone, Salutation, Title 
                         FROM Contact WHERE Id = :contactassignment];
        }


        public Opportunity getOpportunity()
        {
                opportunity = [select Id, AccountId, CloseDate, Name, OwnerId, ProjectedAnnualRevenue__c , StageName,
                            Account.Name, Account.MailingAddressLine1__c, Account.MailingAddressLine2__c, 
                            Account.MailingAddressLine3__c, Account.MailingAddressCity__c, Account.MailingAddressState__c, 
                            Account.MailingAddressZip__c,
                            Owner.Email, Owner.City, Owner.Name, Owner.State, Owner.Phone, Owner.Title
                        from Opportunity where id = :System.currentPageReference().getParameters().get('id')];
                return opportunity;
        }


      private List<CheckedOpportunity> checkedOpportunities;
 
      public List<CheckedOpportunity> getCheckedOpportunities(){
          //only instantiate the list one time
          if (checkedOpportunities==null)
          {
            checkedOpportunities = new List<CheckedOpportunity>();
            List<Opportunity> oppties = [SELECT Id, CloseDate, Name, ProjectedAnnualRevenue__c, RecordType.Name, StageName, 
                            Owner.Email, Owner.City, Owner.Name, Owner.State, Owner.Phone, Owner.Title,
                            Product__c
                FROM Opportunity WHERE AccountId = :opportunity.accountid AND Id <> :opportunity.Id
                    AND RecordType.Name = 'Treasury Management Products'
                            ORDER BY CloseDate DESC];
                        if (oppties != null) {
                                    for (Opportunity oneOpty : oppties){
                                                CheckedOpportunity mo = new CheckedOpportunity(oneOpty);
                                                checkedOpportunities.add(mo);
                                    }
                        }
                        numberOfOppties = [SELECT Count() FROM Opportunity WHERE AccountId = :opportunity.accountid AND Id <> :opportunity.Id
                    AND RecordType.Name = 'Treasury Management Products'];
          }
          return checkedOpportunities;
      }

     
      private List<CheckedOpportunity> checkOpportunities;
 
      public List<CheckedOpportunity> getCheckOpportunities(){
          {
              checkOpportunities = new List<CheckedOpportunity>();
             if (checkedOpportunities != null)
             {
                  for (CheckedOpportunity oneOpty : checkedOpportunities)
                  {
                      if (oneOpty.checked==true)
                      {
                          CheckedOpportunity mo = oneOpty;
                          checkOpportunities.add(mo);
                      }
                  }
             }
          }
          return checkOpportunities;
      }



        // The next methods control navigation through
        // the wizard.  Each returns a PageReference for one of the pages
        // in the wizard. Note that the redirect attribute does not need to
        // be set on the PageReference because the URL does not need to change
        // when users move from page to page.

        public PageReference getContactInfo() 
        {
            return null;
        }

        public PageReference startImp()
        {
                return Page.passportOppStartImp;
        }

        public PageReference selectOpps()
        {
                return Page.passportOppSelectOpps;
        }

        public PageReference selectPrimaryContact()
        {

                 return Page.passportOppSelectContact;
        }

        public PageReference contactDetail()
        {
                return Page.passportOppContactDetail;
        }

        public PageReference contactEdit()
        {
                return Page.passportOppImpContactEdit;
        }

        public PageReference copyAccountAddress()
        {
                thecontact.mailingstreet = opportunity.account.mailingaddressline1__c;
                if (opportunity.account.mailingaddressline2__c != Null) {thecontact.mailingstreet = thecontact.mailingstreet + ' \r\n' + opportunity.account.mailingaddressline2__c;}
                if (opportunity.account.mailingaddressline3__c != Null) {thecontact.mailingstreet = thecontact.mailingstreet + ' \r\n' + opportunity.account.mailingaddressline3__c;}
                thecontact.mailingcity = opportunity.account.mailingaddresscity__c;
                thecontact.mailingstate = opportunity.account.mailingaddressstate__c;
                thecontact.mailingpostalcode = opportunity.account.mailingaddresszip__c;
        update thecontact;
                return Page.passportOppContactDetail;
        }

        public PageReference selectContact()
        {
                return Page.passportOppImpContactEdit;
        }

    public PageReference save() {
        update thecontact;
        if ((thecontact.Phone == null) && (thecontact.OtherPhone==null) && (thecontact.HomePhone==null))
        {
            return Page.passportOppImpContactEdit;
        }
        else
        {
            return Page.passportOppContactDetail;
        }
    }


    public PageReference cancel() {
        PageReference opptyPage = new PageReference('/' + System.currentPageReference().getParameters().get('id'));
        opptyPage.setRedirect(true);

        return opptyPage;
    }

    //Submit the implementation
    //Implementation for an opportunity requires the opportunity and contact IDs
    //The selected contact ID is contained in the contactassignment variable
    //When complete, return to original Opportunty record
    public PageReference passportoppimpsubmit() 
    {
        //This checks to see if all the required fields have been entered.
        //Street, city, state and zip are all required.  
        //For the phone, home phone and other phone, at least one of the three must be entered.
        if ((thecontact.mailingstreet==null) || (thecontact.mailingcity==null) || (thecontact.mailingstate==null) ||(thecontact.mailingpostalcode==null) || ((thecontact.phone==null) && (thecontact.homephone==null) && (thecontact.otherphone==null)))
        {
            return Page.passportOppContactDetail;
        }
        else
        {
            if (passport_master_record==null) passport_master_record = new PASSPORT_Implementation__c();
                passport_master_record.contact__c= contactassignment;
            Database.SaveResult sr = Database.insert(passport_master_record, false);
            string impID = sr.getId();
            PASSPORT_Implementation_Opportunities__c originating_Opp = new PASSPORT_Implementation_Opportunities__c ();
            originating_Opp.Originating_Opportunity__c = true;
            originating_Opp.Opportunity__c = opportunity.Id;
            originating_Opp.PASSPORT_Implementation__c = impID;
            insert originating_Opp;

            //Save linked opportunities
            integer i = 0;
            while (i < numberOfOppties)
            {
                if (checkedOpportunities[i].checked == true)
                {
                    PASSPORT_Implementation_Opportunities__c linked_Opp = new PASSPORT_Implementation_Opportunities__c ();
                    linked_Opp.Opportunity__c = checkedOpportunities[i].opportunity.id;
                    linked_Opp.PASSPORT_Implementation__c = impID;
                    insert linked_Opp;
                }
                i++;
            }
            string pageURL = 'tapp0-api.salesforce.com';
            string mySessionId = UserInfo.getSessionId();
            string forcedURL = 'http://passportfmr-dev.suntrust.com/launchpad.aspx—id=' + impID + '&sessionid=' + mySessionId + '&url=https://tapp0-api.salesforce.com/services/Soap/class/PASSPORT_Web_Services';
            PageReference opptyPage= new PageReference(forcedURL);

//            PageReference opptyPage= new PageReference('/' + System.currentPageReference().getParameters().get('id'));
            opptyPage.setRedirect(true);
            return opptyPage;
        }
    }
}

Now for the Visualforce page:

 

jwetzlerjwetzler
Okay that's a lot of information there and I'm not totally sure where to begin. The smaller the example that demonstrates your issue, the easier it will be for us to debug it.

That being said, a few suggestions.  First, why does getContact() return a list when you know there's only going to be one contact? 
Is that just because you wanted it displayed in table format?  (Hint, pageBlockTable would probably be better if you are going to use a dataTable in a pageBlock, but that does not matter to your particular problem.  Also look at headerValue and value on column).

Also there is no need for you to have an action on your actionSupport component.  It's not doing anything, just returning null.  That's what it will do if you don't specify an action.  Again just a suggestion to clean things up, should not change behavior.

But, have you put a System.debug in your setContactAssignment and verified that your setter is actually getting called on change? 
I made a very simple page with a selectRadio component that updates an outputPanel with the value that was selected and that worked fine, so I know actionSupport with onchange will work.

Sorry to keep the back and forth going. But if you can try to see what's going on with System.debug statements, that will help a lot towards figuring out what is going wrong in your page.
forcewithuforcewithu

Sorry for the overload of code, Jill.  I thought you wanted to see everything, since I'd previously sent the most relevant snippets.  Thanks for the suggestions to improve my code.  As I said, this was something done by someone with NO Salesforce experience in just a very few weeks; so I'll take all the helpful suggestions I can get.  :smileyhappy:

As for the System.debug, all it did was verify what I already knew: no event is firing when a radio button is selected.  That's my whole problem.  No matter what I do with actionSupport, I can't seem to get it to actually fire an event.  As soon as I click on the Select button, an event is fired and everything works as desired.  If I could just get an event (ANY event) to fire when the user clicks on a radio button, I can design the code to handle whatever event that is.  But thus far, NO EVENT fires.

Could you possibly send your snippet of code that works?  I have no problem reengineering my code to work with something that works.  Until I can find some code that causes an event to fire, I'm kind of at a loss.

John

forcewithuforcewithu

FOUND IT!

I needed to move the actionSupport tag up one level.  Instead of being a child to selectOptions,
it needed to be a sibling (child of selectRadio).  So, it needed to look like this:

Code:
<apex:selectRadio id="Contact_Selection" value="{!ContactAssignment}" layout="pageDirection" onchange="{!ContactInfo}" required="true">
   <apex:selectOptions value="{!ContactList}" />
   <apex:actionSupport event="onclick" reRender="theForm" status="status"/>
</apex:selectRadio><


 Thanks for your help!

-John

jwetzlerjwetzler
D'oh.  To think how much time we could have saved had I noticed that in your very first post.  Sorry :)
dchasmandchasman
Grrrrr - I did not see it either - sorry about that.

Just so you know the requirement that we maintain the flexibility of apex:actionSupport has tripped up a ton of folks (my own team on occasion) because of the spatial relationship between the apex:actionSupport component and the component it is enhancing. We're looking at things like providing more built in event-to-action attributes on components like apex:selectRadio in the future to remove this very common error condition.