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
TehNrdTehNrd 

If immediate="true" rerender does not appear to work

I am having issues using the immediate attribute within actionSupport. The documentation says that "If set to true, the action happens immediately and any field validation rules are skipped." It doesn't mention anything about rerendering or data binding so I'm a little confused. Here is my problem:

I have a select list of contacts. When a contact is selected, a form with inputFields is rerendered to display the data of the selected contact. Some of these fields are required. If a field is null and you try to select a different contact you get an error message that the field is required. This is no good, so I added the immediate attribute to the actionSupport but now it does not appear to be rerendering the form.

Any ideas, suggestions?

Page:
Code:
<apex:page controller="input" >

<apex:form >
  <apex:selectList value="{!contactID}" size="5">
     <apex:selectOptions value="{!contacts}" />
     <apex:actionSupport event="onchange" action="{!updateContact}" rerender="form" immediate="true"/>
  </apex:selectList>
  <apex:pageBlock >
     <apex:panelGrid columns="2" id="form">
        Full Name: <apex:outputField value="{!c.Name}"/>
        Email: <apex:inputField value="{!c.Email}" required="true"/>
        Title: <apex:inputField value="{!c.Title}" required="true"/>
        Phone: <apex:inputField value="{!c.Phone}" required="true"/>
     </apex:panelGrid>  
  </apex:pageBlock>
</apex:form>

</apex:page>

Controller:
Code:
public class input {
    public String ContactId {set; get;}
    public Contact c {set; get;}
    private List<SelectOption> contacts;
    private Map<Id,Contact> contactMap = new Map<Id,Contact>();

    public List<SelectOption> getContacts(){
       if(contacts == null){
           Contact [] cons = [select Id, Name, Title, FirstName, LastName, Phone, Email from Contact limit 10];
           contactId = cons[0].Id;
           contacts = new List<SelectOption>();
    
           for(Contact c : cons){
              contacts.add(new SelectOption(c.ID,c.Name));
              contactMap.put(c.Id,c);
           }
       }
       return contacts;
    }
   
    public PageReference updateContact(){
        c = contactMap.get(ContactID);
        return null;
    }      
}

 

Best Answer chosen by Admin (Salesforce Developers) 
mtbclimbermtbclimber
Yes, it did seem strange. There is still some strangeness here though that these are inputfields, maybe your subsequent process requires those fields to be non-null?  It may seem odd to your users that if they add a title (or other value) where there was none that it's not saved back but I suppose in certain circumstances you want them to be able to change the email for this one occaision perhaps.

Enough of the critiquing and on to what I hope will be a viable solution for you.  It appears you are not concerned with the values that a user might change between selections and as such you can leverage  apex:actionRegion to control which area of the page is included in the post back to your controller. If you exclude the inputFields from the region then those values will not be sent back but the selected contactId will be. Here's how your page would look (same controller):

PAGE:
<apex:page controller="input" >
    <apex:form >
      <apex:actionRegion>
          <apex:selectList value="{!contactID}" size="5">
             <apex:selectOptions value="{!contacts}" />
             <apex:actionSupport event="onchange" action="{!updateContact}" rerender="form"/>
          </apex:selectList>
      </apex:actionRegion>
      <apex:pageBlock >
         <apex:panelGrid columns="2" id="form">
            Full Name: <apex:outputField value="{!c.Name}"/>
            Email: <apex:inputField value="{!c.Email}" required="true" />
            Title: <apex:inputField value="{!c.Title}" required="true"/>
            Phone: <apex:inputField value="{!c.Phone}" required="true"/>
         </apex:panelGrid>  
      </apex:pageBlock>
    </apex:form>
</apex:page>

 This may work for you as long as the user has to invoke another action (not included in the page yet) to actually use the values provided/applied to the inputFields.

If you (or anyone else reading this later) wish to do something with the data in the controller on the postback (actionSupport invocation) you will have to remove the required attributes and move the validation to your controller.  We did a lot of work in this area in Summer '08 if you haven't checked it out yet refer to page 62 in the visualforce developer guide (PDF) for an example and the new message class and methods in the ApexPages namespace which are documented in appendix B on page 82.



Message Edited by mtbclimber on 06-19-2008 06:52 AM

All Answers

TehNrdTehNrd
Well, I've done some more testing and it appears that when you set immediate to true in the actionSupport for the selectList the setter method for the contactId is not executing. I have tried adding another actionSupport method with the action as the setter method but that does not appear to work? How can I force it to execute even if immediate="true"?





Message Edited by TehNrd on 06-18-2008 04:40 PM
mtbclimbermtbclimber
immediate="true" does bypass validation but it also bypasses the set-value phase in the life cycle so the values are not updated.  immeditate is useful for things like cancel and where you just want to execute an action directly that is not dependent on data changes, i.e. remove me from a collection, etc.

Can you explain what your goals are around this? It seems your ambition to allow the user to bypass validation may be at odds with your stated requirement for those input elements to be truly required at save time assuming you are going to offer saving of the entire collection.

Please advise so we can guide you appropriately.

Regards,
TehNrdTehNrd
Yes, I will admit at first it does seem strange what I am doing. I will go into more detail below but first a quick overview of what this is for. This is part of a larger project where we are completely rebuilding our entire deal registration/deal forward/convert lead process with VF pages (no more standard convert button) .

The specific part that is giving us issues is the deal forwards. All of our sales must go through a reseller. A deal forward is when an opp does not yet have a selected reseller we will forward one the chance to be the partner for it. But I digress, here is the main issue.

We will be sending an email to one of our resellers with the information (phone, title, email, etc) of a single Contact, the one that is selected. A button on the opportunity launches this VF page and a selectList is populated with all of the Contacts for that Account. On the page there is a form that has several inputFields for the contact (phone, title, email, etc) and these are automatically populated upon the selection of a Contact from the list. All of these fields are required before the user can hit the Send Email button (not change contact) which does all of the logic, sends email, and returns user to opp page.

So the dilema is how to make all of these form fields required but only for the Send Email action. If I add the required attribute to the inputFields everything is okay until you select a Contact where one of the fields is null, say Title. If Title is null and you then try to select a different contact you will get an error message saying Title is required. But really it's not required when a user is changing contacts rather when the user clicks the Send Email button.

So I added the immediate attribute to the actionSupport for the select list hoping it would ignore the requiredness, and it does, but as we have figured out the Id of the newly selected contact is not set so when the form re-renders nothing changes.

Sorry that took so long but I wanted to make it as clear as possible. If anything doesn't make sense please let me know.

Thanks,
Jason



mtbclimbermtbclimber
Yes, it did seem strange. There is still some strangeness here though that these are inputfields, maybe your subsequent process requires those fields to be non-null?  It may seem odd to your users that if they add a title (or other value) where there was none that it's not saved back but I suppose in certain circumstances you want them to be able to change the email for this one occaision perhaps.

Enough of the critiquing and on to what I hope will be a viable solution for you.  It appears you are not concerned with the values that a user might change between selections and as such you can leverage  apex:actionRegion to control which area of the page is included in the post back to your controller. If you exclude the inputFields from the region then those values will not be sent back but the selected contactId will be. Here's how your page would look (same controller):

PAGE:
<apex:page controller="input" >
    <apex:form >
      <apex:actionRegion>
          <apex:selectList value="{!contactID}" size="5">
             <apex:selectOptions value="{!contacts}" />
             <apex:actionSupport event="onchange" action="{!updateContact}" rerender="form"/>
          </apex:selectList>
      </apex:actionRegion>
      <apex:pageBlock >
         <apex:panelGrid columns="2" id="form">
            Full Name: <apex:outputField value="{!c.Name}"/>
            Email: <apex:inputField value="{!c.Email}" required="true" />
            Title: <apex:inputField value="{!c.Title}" required="true"/>
            Phone: <apex:inputField value="{!c.Phone}" required="true"/>
         </apex:panelGrid>  
      </apex:pageBlock>
    </apex:form>
</apex:page>

 This may work for you as long as the user has to invoke another action (not included in the page yet) to actually use the values provided/applied to the inputFields.

If you (or anyone else reading this later) wish to do something with the data in the controller on the postback (actionSupport invocation) you will have to remove the required attributes and move the validation to your controller.  We did a lot of work in this area in Summer '08 if you haven't checked it out yet refer to page 62 in the visualforce developer guide (PDF) for an example and the new message class and methods in the ApexPages namespace which are documented in appendix B on page 82.



Message Edited by mtbclimber on 06-19-2008 06:52 AM
This was selected as the best answer
TehNrdTehNrd
Thanks Andrew. It looks like this will do the trick as I don't care if values aren't saved to memory when choosing different Contacts. The user is also invoking another action method later, Send Email. I actually tried using actionRegion before but I was using it in the wrong place, wrapped around the inputFields.

A few follow up comments. I am using input fields as I want to leverage the out of the box features such as error message automatically showing up for the correct field and validation on fields such as email addresses. And yes, my subsequent process, sending the email, requires these fields be non-null as they will be merged in to the body of the email. I am never actually saving these values with a DML statement but I am just allowing the user to proof the values and make any minor changes before I merge them into the email.

Thanks again for the help.

Also looking forward to Tour de Force in Seattle.

-Jason


Message Edited by TehNrd on 06-19-2008 09:19 AM
developer-forcedeveloper-force
Thanks a lot it helped solve the problem with populating select list with actionSupport component.
SteveBowerSteveBower
Thanks as well. In a simple select list the controller value wasn't being updated and I was all over the place trying to figure it out. Who would have thought 'immediate="true"' would have something to do with the selected option being set given it's documentation.

This needs to be fixed in the documentation.

Thanks for the useful thread, Steve.
JoshVHJoshVH
Can anyone explain why when you use the actionRegion tag around an inputField the Salesforce styling is lost?  If you place the actionRegion tag around a pageBlockSection the Salesforce styling is maintained.  In my case I want the actionRegion tag to only postback one field so I can dynamically alter what fields are visible on the rest of the page based on the selection in the single field.  If I don't have the actionRegion tag around this one field I run into the required fields problems discussed earlier in this thread.
mtbclimbermtbclimber
Yes this is because of the way pageblocksection behaves as it is not seeing inputfield as it's direct child when you wrap it with an action region.  Check out pageblocksectionitem. You'll have to specify the label yourself (for that use the $ObjectType global) but you should be able to effectively wrap the inputField, maintain the styling and get the level of control you are after.
JoshVHJoshVH
That worked.  I had to put the actionRegion directly around the inputField inside of the pageBlockSectionItem.  I have pasted a code sample below for anyone else who might need to do this.

 
Code:
<apex:pageBlockSectionItem >
    <apex:outputLabel value="Client" for="client"/>
    <apex:actionRegion>
<apex:inputField id="client" value="{!object.client__c}" required="true"> <apex:actionSupport event="onblur" action="{!RetrieveAccount}" rerender="otherfield"/> </apex:inputField> </apex:actionRegion>
</apex:pageBlockSectionItem>

 

mtbclimbermtbclimber
Great! Thanks for posting the solution. What I meant by $ObjectType was this:

Code:
<apex:pageBlockSectionItem >
    <apex:outputLabel value="{!$ObjectType.My_Object__c.fields.client__c.label}" for="client"/>
    <apex:actionRegion>
        <apex:inputField id="client" value="{!object.client__c}" required="true">
            <apex:actionSupport event="onblur" action="{!RetrieveAccount}" rerender="otherfield"/>
        </apex:inputField>
    </apex:actionRegion>
</apex:pageBlockSectionItem>

In this case, assuming My_Object__c is the  name of your custom object for the variable "object".  This will give you the field label dynamically including translations.


JoshVHJoshVH
Thanks for the clarification.  I realized after I posted that I forgot to put that in there.  Is there any documentation that shows everything that is available in the $ObjectType global variable?  For instance can you get information about the object besides the fields?  I imagine you can but I can't find any documentation.  Thanks.
hemantgarghemantgarg

I am facing same issue while using immediate=true and actionRegion, can we put the actionRegion around each row in a pageblocktable ?

Jaffer Ali.Jaffer Ali.

This solutions helps me a lot thanks.Un fortunately there are lot of required fields on page so now I am going to change these logics in controller.For only one purpose we need to do update our code , it needs to be changed.

rcravenrcraven

I got an idea, why not update the description of the immediate attribute so that we are not tripping over this behaviour

Akshay DeshmukhAkshay Deshmukh
you can check my post at following link for action:region tag
http://dattarajsfdc.wordpress.com/
chvl narayanachvl narayana
Hii All
I am also facing this type of problem.
please find the below code send me correct one.

here
 <apex:inputField value="{!customer.Name}" ><apex:actionSupport  event="onchange" action="{!searchCustomerSSN}" /></apex:inputField>
Nmae is the Unique. If any duplicate entered immediatly i wnat to display error. 
in vf page there are some required fields 
  <apex:inputField value="{!customer.First_Name__c}" />
                <apex:inputField value="{!customer.Last_Name__c}" />
                <apex:inputField value="{!customer.Date_Of_Birth__c}" />
                <apex:inputField value="{!customer.Age__c}"  />
after completion of customer name there is action method is performaing and displaying the errors
Errors

First Name: You must enter a value
Last Name: You must enter a value
Date Of Birth: You must enter a value
Phone: You must enter a value
Email: You must enter a value

i dont want to show this errors when i entered in customer name.
 <apex:pageBlock id="pb">
            <apex:pageMessages ></apex:pageMessages>                                                    
            <apex:pageBlockSection columns="2" title="Patient Personal Details" collapsible="true" id="pbs1">
               
                <apex:inputField value="{!customer.Name}" ><apex:actionSupport  event="onchange" action="{!searchCustomerSSN}" /></apex:inputField>
                
                <apex:inputField value="{!customer.First_Name__c}" />
                <apex:inputField value="{!customer.Last_Name__c}" />
                <apex:inputField value="{!customer.Date_Of_Birth__c}" />
                <apex:inputField value="{!customer.Age__c}"  />
                <apex:inputField value="{!customer.Gender__c}" />
               
            </apex:pageBlockSection>
</apex:pageBlock>