+ Start a Discussion
Baird_SBaird_S 

Revealing adderror() message in VF page?

First off, thanks to Bob Buzzard and everyone else I've been learning from in these discussion boards.  You've gotten me this far, and with a little more help I think I'll be home.

 

I'm trying to reveal an error message, "That event is already full" when a user tries to sign up for an event that's sold out (slots_remaining < 1).

 

The relevant part of the visualforce code is 5 lines from the bottom, where I'd like the error message to appear below the inputfield for slots_remaining__c.

 

This is the page (public_event_select_page):

<apex:page showheader="false" cache="false" standardController="Campaign" extensions="Public_Event_Controller2">
<apex:stylesheet value="{!$Resource.wg_styles}"/>

        <apex:detail subject="{!$CurrentPage.parameters.cid}" relatedList="false" title="false"/>

            <apex:form >
                <apex:dataTable value="{!campaign}" var="c" cellPadding="10" border="0">
                  <apex:column width="100px" style="vertical-align: top;">
                    <apex:facet name="header">Name</apex:facet>
                    <apex:commandLink action="{!prepsignup}" value="{!c.name}" id="theButton">
                        <apex:param assignTo="{!passCampID}" value="{!c.ID}" name="passCampID"/> 
                        </apex:commandLink> 
                  </apex:column>
                  <apex:column style="vertical-align: top;">
                    <apex:facet name="header">Short description</apex:facet>
                    {!c.description}
                  </apex:column>
                  <apex:column style="vertical-align: top;">
                    <apex:facet name="header">Date and time</apex:facet>
                    <apex:outputfield value="{!c.Event_Time_Shifted__c}"/>
                 
                  </apex:column>
                  <apex:column style="vertical-align: top;">
                    <apex:facet name="header">Cost</apex:facet>
                     <apex:outputText value="{0,number,$#,####.##}">
                        <apex:param value="{!c.Event_Cost__c}" />
                     </apex:outputText>
                    
                  </apex:column>
                  <apex:column style="vertical-align: top;">
                    <apex:facet name="header">Places remaining</apex:facet>
                     <apex:inputfield value="{!c.Slots_remaining__c}" />                  
                  </apex:column>
                </apex:dataTable>
            </apex:form>    
        </apex:page>

 And the relevant part of the controller (public_event_controller):

 

public PageReference prepSignup() {
    system.debug('Beginning prepSignup.  passCampID is now '+ passCampID);
    Camp = [SELECT Id ,Name, Description, Description_Long__c, Event_Cost__c, 
        Event_Location__c, Event_Date_time__c, Waiver_Required__c,
        Event_Time_Shifted__c, Slots_Remaining__c, CnP_URL__c FROM Campaign 
        WHERE id = :passCampID limit 1];
        system.debug('Camp.ID is now ' + Camp.ID);
    if (camp.Slots_remaining__c >= 1) {
        results = null;
        createNewLead = false;
        system.debug('Camp.slots_remaining__c is now '+ camp.slots_remaining__c);
        PageReference signUpForEvent = Page.Public_Event_Signup_Page2;
        signUpForEvent.setRedirect(false);
        return signUpForEvent;}
    else {
        camp.slots_remaining__c.addError('This event is full.'); 
        return null;
        }
} // END PREPSIGNUP()

At present the controller behaves as desired, except that no error message appears.

 

Maybe the problem is that when the controller returns null and visualforcepage rerenders the initial page (public_event_select_page2), the new error message is no longer associated with the campaign.  the campaigns displayed on thep age are selected by

 

public List<Campaign> getCampaign() {
    return [select campaign.name, id, Description, Event_Date_Time__c, Event_Time_Shifted__c, 
    recordtypeid, Event_Cost__c,  Slots_Remaining__c, Waiver_Required__c, CnP_URL__c from Campaign where 
    (Event_Date_Time__c >= Today and (recordtype.name = 'Public Event' 
    or recordtype.name = 'Volunteer Event')) ORDER BY Event_Date_Time__c ASC];
}

 I've tried to follow Bob Buzzard's example but since he's iterating through an object differently, I'm not surely how to get the error message back to the visualforce page.

 

Thanks in advance for your help,

Baird 

Devendra@SFDCDevendra@SFDC

 

Hi,

 

Try this:

 

Use  <apex:pageMessages ></apex:pageMessages> statement below the <apex:form> tag.

 

Hope this helps.

 

Thanks,

Devendra S

Baird_SBaird_S

Thanks, Devendra, that's almost perfect.  

 

But it puts the error message at the top of the page.  Do you know how I can position it right under the field itself?

 

Baird

 



 

 

hemantgarghemantgarg

Hi,

 

The posistion of <apex:pagMessages /> can be at anywhere on the vf, altenatively you can put a <div> element under inpuField and conditionally display that div with error message.

Devendra@SFDCDevendra@SFDC

 

Hi,

 

Please follow below link to display error message at field level:

 

http://bobbuzzard.blogspot.com/2011/04/field-level-error-messages-with_29.html

 

Hope this helps.

 

Thanks,

Devendra

bob_buzzardbob_buzzard

Hah - a circular reference if I'm not mistaken.

 

I suspect that what is happening is that you are retrieving the records anew each time, which means that you will lose the error message you added to the copy you originally retrieved.

 

I'd try caching the campaigns rather than retrieving each time:

 

private List<Campaign> mCampaign;

public List<Campaign> getCampaign() {
    if (null==mCampaign)
    {
        mCampaign= [select campaign.name, id, Description, Event_Date_Time__c, Event_Time_Shifted__c, 
    recordtypeid, Event_Cost__c,  Slots_Remaining__c, Waiver_Required__c, CnP_URL__c from Campaign where 
    (Event_Date_Time__c >= Today and (recordtype.name = 'Public Event' 
    or recordtype.name = 'Volunteer Event')) ORDER BY Event_Date_Time__c ASC];
    }
   
    return mCampaign;
}

that way you are always dealing with the same instance that you add the error to. 

Baird_SBaird_S

Thanks Bob, Devendra, and Hermant for your quick responses.  I was out with clients yesterday and couldn't respond.

 

Still no solution.  I've tried Bob's suggesting to cache the SOQL query results, and no luck.

 

I'm wondering whether the field.adderror() is being attached to the wrong object, ie one that doesn't get queried when the list of events(campaigns) on the VF page is revealed.

 

I'll post my full controller code at the bottom, but here's the sequence that I think matters:

 

1. The page reveals the results of the SOQL query for events(campaigns) that haven't yet passed.  As Bob suggested, I've changed the code to cache the results so they don't change when I refresh the page.

 

public List<Campaign> getCampaign() {
    if (null==mCampaign)
    {
        mCampaign= [select campaign.name, id, Description, Event_Date_Time__c, Event_Time_Shifted__c, 
    recordtypeid, Event_Cost__c,  Slots_Remaining__c, Waiver_Required__c, CnP_URL__c from Campaign where 
    (Event_Date_Time__c >= Today and (recordtype.name = 'Public Event' 
    or recordtype.name = 'Volunteer Event')) ORDER BY Event_Date_Time__c ASC];
    }
   
    return mCampaign;
}

 

2. When a user clicks on one of the campaign names (CommandURLs), the page sets the passCampID parameter and invokes prepsignup().  

 

public PageReference prepSignup() {
    Camp = [SELECT Id ,Name, Description, Description_Long__c, Event_Cost__c, 
        Event_Location__c, Event_Date_time__c, Waiver_Required__c,
        Event_Time_Shifted__c, Slots_Remaining__c, CnP_URL__c FROM Campaign 
        WHERE id = :passCampID limit 1];
    if (camp.Slots_remaining__c >= 1) {
        results = null;
        createNewLead = false;
        PageReference signUpForEvent = Page.Public_Event_Signup_Page2;
        signUpForEvent.setRedirect(false);
        return signUpForEvent;}
    else {
        camp.slots_remaining__c.addError(camp.name + ' is full.'); 
        return null;
        }

3. Prepsignup() SOQL uses the passCampID to select the chosen event "camp".  If the event still has spaces available, the controller invokes the next VF page and signs the user up for the event.  If it doesn't have spaces left, the controller adds the error to camp.slots_remaining__c, and returns null, which should theoretically take us back to the list of events, but this time with the error message.

 

The sequence works as planned, except there's no field-level error message visible.

 

My question: when the controller adds the error to camp.slots_remaining__c, is that registered within Salesforce as the same campaign instance as the one that's returned by the SOQL query Bob suggested in step one?

 

My second question: In Bob's example, he creates a value

 

Boolean error=false;

 and then sets that to true when the error condition exists within one of the iterations within it.

 

Was this error value essential to revealing the error messages?  I'd assumed it wasn't, but maybe that's what I'm missing.

 

Once again, many thanks for your help.

 

Baird

 

Full controller code below:  (Full VF page code is in first post).

 

public class Public_Event_Controller2 {


public Public_Event_Controller2(ApexPages.StandardController stdController) {
}


//DECLARE VARIABLES 
Public campaign camp;
Public string passCampID {get; set;}
Public Contact pcontact;
public List<String> results {get; set;}
Public Lead newlead {get; set;}
Public Campaignmember campmmbr;
Public Opportunity Op;
Public contact TempContact;
Public lead tempLead;
Public boolean paidevent;
Id leadrt = [select Id from Recordtype where name = 'Online Signup' AND SobjectType ='Lead'].Id;
Public boolean createnewlead {get; set;}
Public boolean readytosubmit {get; set;}
Public boolean Agreed_To_Waiver {get; set;}
Public boolean Must_Sign_Waiver {get; set;}
Public boolean enewsletters {get; set;}
Boolean CampmmbrExists = false;
Boolean error = false;
Public string companyString {get; set;}
private List<Campaign> mCampaign;

public List<Campaign> getCampaign() {
    if (null==mCampaign)
    {
        mCampaign= [select campaign.name, id, Description, Event_Date_Time__c, Event_Time_Shifted__c, 
    recordtypeid, Event_Cost__c,  Slots_Remaining__c, Waiver_Required__c, CnP_URL__c from Campaign where 
    (Event_Date_Time__c >= Today and (recordtype.name = 'Public Event' 
    or recordtype.name = 'Volunteer Event')) ORDER BY Event_Date_Time__c ASC];
    }
   
    return mCampaign;
}

/*
public void PrepSignup() {
Camp = [SELECT Id ,Name, Description, Description_Long__c, Event_Cost__c, 
    Event_Location__c, Event_Date_time__c, Waiver_Required__c,
    Event_Time_Shifted__c, Slots_Remaining__c, CnP_URL__c FROM Campaign 
    WHERE id = :ApexPages.currentPage().getParameters().get('cid') limit 1];
    results = null;
    createNewLead = false;
        return;
} // END OF PREPSIGNUP
*/

//WHEN CAMPAIGN SELECTED, MAKE SURE IT'S STILL GOT SLOTS OPEN
public PageReference prepSignup() {
    system.debug('Beginning prepSignup.  passCampID is now '+ passCampID);
    Camp = [SELECT Id ,Name, Description, Description_Long__c, Event_Cost__c, 
        Event_Location__c, Event_Date_time__c, Waiver_Required__c,
        Event_Time_Shifted__c, Slots_Remaining__c, CnP_URL__c FROM Campaign 
        WHERE id = :passCampID limit 1];
        system.debug('Camp.ID is now ' + Camp.ID);
    if (camp.Slots_remaining__c >= 1) {
        results = null;
        createNewLead = false;
        system.debug('Camp.slots_remaining__c is now '+ camp.slots_remaining__c);
        PageReference signUpForEvent = Page.Public_Event_Signup_Page2;
        signUpForEvent.setRedirect(false);
        return signUpForEvent;}
    else {
        ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, camp.name + ' is full.'));
        camp.slots_remaining__c.addError(camp.name + ' is full.'); 
        error = true;
        return null;
        }
} // END PREPSIGNUP()

    
//PASS IN DATA ABOUT THIS PARTICULAR CAMPAIGN
public Campaign getCamp() {     
return camp;
}       
 
//CONTACT VARIABLE TO HOLD CONTACT FIELDS
public Contact getpContact(){
if (pcontact == null) {
pcontact = new Contact();
}
return pcontact;   
}
 
//RETURN TO LIST FUNCTION
public PageReference ReturnToList(){
PageReference ReturnToList = Page.Public_Event_Select_Page2;
ReturnToList.setRedirect(true);
return ReturnToList;}

//SAVE FUNCTION
public PageReference save(){
//MAKE SURE THEY'VE AGREED TO THE WAIVER
        system.debug('Agreed_to_Waiver '+ Agreed_to_Waiver);
        system.debug('Waiver Required '+ camp.Waiver_Required__c);
    if (Agreed_to_Waiver == false && camp.Waiver_Required__c == true) {
        Must_Sign_Waiver = true;
        return null;}
    //IF NOT ALREADY DONE, CHECK EMAIL, ZIP CODE AGAINST EXISTING LEADS AND CONTACT        
    system.debug('if results null identifysigner.  results is ' + results);
    if (results == null || results[0] == '701T0000000C0d9IAC') identifySigner();
    if (createNewLead == true) return null; 
    system.debug('readyToSubmit is ' + readyToSubmit);
    if (readyToSubmit) {
    insertCampaignMember(results[0], results[1]);
    if (pcontact.over_18__c == true) {
        system.debug('Just passed pcontact.over_18__c is true, call SetOver18');
        SetOver18();
        } // END SETOVER18
    if (enewsletters == true) SignUpNewsletter();
    //REDIRECT TO THANKYOU PAGE
    PageReference Thanks_Page = Page.Public_Event_Thanks_Page;
    Thanks_Page.setRedirect(false);
    return Thanks_Page;
    } // END IF READYTOSUBMIT
    else return null;
    }  //END SAVE


//Identify Contact or Lead
public String [] IdentifySigner() { 
//declare a list to store results
results = new String[2];
//If contact exists
    Contact[] pccheck = [Select ID, AccountID from Contact where email = :pcontact.email];
    if (pccheck.size() > 0) {
    results[0] = pccheck[0].id;
    results[1] = 'Contact';
    readyToSubmit = true;
    return results;
    }
    ELSE {
        //If lead exists
        Lead[] lcheck = [Select Id from Lead where email = :pcontact.email];
        if (lcheck.size() > 0) {
        results[0] = lcheck[0].Id;
        results[1] = 'Lead';
        readyToSubmit = true;
        return results;
        }
        ELSE 
        {
            //does contact exist based on name and zip code?
            pccheck = [Select ID, AccountID from Contact 
                where (firstname = :pcontact.firstname AND lastname = :pcontact.lastname
                AND  MailingPostalCode = :pcontact.MailingPostalCode)];
            if (pccheck.size() > 0) {
            results[0] = pccheck[0].ID;
            results[1] = 'Contact';
                readyToSubmit = true;
            system.debug('Passed: Identified contact by name and zip code');
            return results;
            }
            ELSE {
                //does LEAD exist based on name and zip code?
                lcheck = [Select ID, firstname, lastname, PostalCode from Lead 
                    where (firstname = :pcontact.firstname AND lastname = :pcontact.lastname
                    AND PostalCode = :pcontact.MailingPostalCode)];
                if (lcheck.size() > 0) {
                results[0] = lcheck[0].Id;
                results[1] = 'Lead';
                        readyToSubmit = true;
                system.debug('Passed: Identified lead by name and zip code');
                
                return results;
                } //end does Lead exist based on name and zip code?
                ELSE {
                    //if enternewlead == null go back for more contact info
                    if (createnewlead == false) {
                        createnewlead = true;
                        results[0] = '701T0000000C0d9IAC'; //This is just garbage filler so that we can return results.
                        results[1] = 'Lead';
                        return results;
                    }
                    else //create new lead
                    {       
                        if (pcontact.description == null) {
                            system.debug('passed pontact.description == null');                      
                            companyString = 'none';
                            system.debug('just set companyString to none; did it take?  companyString is ' + companyString);
                            }  
                            else {
                            companyString = pcontact.description;
                            system.debug('just passed else, set companyString to ' + pcontact.description);
                            }
                        system.debug('companyString is ' + companyString);   
                        lead newlead = new Lead (lastname = pcontact.lastname, 
                        firstname=pcontact.firstname,
                        email=pcontact.email, 
                        company=companyString, 
                        street=pcontact.MailingStreet,
                        city=pcontact.MailingCity,
                        state=pcontact.MailingState,
                        postalCode=pcontact.MailingPostalCode,
                        phone=pcontact.Phone,
                        volunteer_interests__c=pcontact.Volunteer_Interests__c,
                        leadsource='Online Volunteer Signup',
                        RecordTypeID = [select ID from RecordType where name = 'Online Signup' and 
                        SObjectType = 'Lead'].id); 
                        insert newlead;
                        createNewLead = false;
                        results[0] = newlead.id;
                        results[1] = 'Lead';
                        system.debug('newlead is ' + newlead);
                        system.debug('newlead firstname is ' + newlead.firstname);  
                        readyToSubmit = true;            
                        return results;
                        } // end else create new lead
                    } //end if enternewlead==null go back for more info
               } // end ELSE does lead exist based on zipcode
           } // end ELSE does contact exist based on zipcode
    } // end ELSE does lead exist based on email?
} // end does contact exist based on email?

public void InsertCampaignMember(id memberID, string mtype) {
    getcamp();
    // Instantiate CampMmbr to hold data
    campmmbr = new CampaignMember(
        campaignid = camp.id,
        status = 'Signed e-petition');
    // Does campmmbr already exist?
    if (mtype == 'Contact') {
        system.debug('Passed insertCampaignMember, mtype = contact');
        CampaignMember[] ccheck = [select id, contactid, campaignid from CampaignMember where 
                contactid = :memberid and campaignid = :camp.id];
        if (ccheck.size() > 0) {
                system.debug('Passed insertCampaignMember, ccheck.size() > 0');
            campmmbr = ccheck[0];
            system.debug('Just set campmmbr to ' + campmmbr.id);
            system.debug('campmmbr.contactid is now ' + campmmbr.contactid);
            campmmbr.status = 'Responded Yes';
            update campmmbr;
            return;
            } // END IF campmmbr exists based on contact id
                else {
                        system.debug('Passed insertCampaignMember, else insert campmmbr');
                campmmbr.contactid = memberID;
                campmmbr.status = 'Responded Yes';
                if (camp.waiver_required__c) 
                    campmmbr.Agreed_to_Waiver__c = Agreed_To_Waiver;
                insert campmmbr;        
                return;}
                        }
        else {
            //assume mtype == lead
                system.debug('Passed else insertCampaignMember, mtype = lead');
            CampaignMember[] lcheck = [select id, leadid from CampaignMember where leadid = :memberid
                        and campaignid = :camp.id];
            if (lcheck.size() > 0){
                        system.debug('Passed insertCampaignMember, lcheck.size() > 0');
                    campmmbr = lcheck[0];
                    system.debug('Just set campmmbr to ' + campmmbr.id);
                    system.debug('campmmbr.leadid is now ' + campmmbr.leadid);
                campmmbr.status = 'Responded Yes';
                if (camp.waiver_required__c) 
                    campmmbr.Agreed_to_Waiver__c = Agreed_To_Waiver;
                update campmmbr;
                return;
                } // END IF campmmbr exists based on lead id
                    // IF NO EXISTING CAMPMMBR
                    else {
                    system.debug('Passed else INSERT NEW CAMPMMBR, right now memberid is ' + memberID);
                    campmmbr.leadid = memberID;
                    campmmbr.status = 'Responded Yes';
                    if (camp.waiver_required__c) 
                        campmmbr.Agreed_to_Waiver__c = Agreed_To_Waiver;
                    insert campmmbr;
                    system.debug('Just inserted campmmbr ' + campmmbr.id);
                    system.debug('campmmbr.leadid is now ' + campmmbr.leadid);
                    system.debug('campmmbr.status is now ' + campmmbr.status);
                    // system.debug('newlead is now ' + newlead.id);                 
                    }       
                    } // END else assume mtype == lead
                } // END method

public PageReference SignUpNewsLetter() {
        system.debug('starting SignUpNewsletter(), campmmbr.contactid is ' + campmmbr.contactid);
        if (campmmbr.contactid != null) 
        {
        system.debug('SignUpNewsletter() determined campmmbr.contactid !=null, campmmbr.contactid is ' + campmmbr.contactid);
        tempContact = [select id, mailing_lists__c from Contact where id = :campmmbr.contactid ];
        system.debug('Found that tempContact.mailing_lists__c is' + tempContact.Mailing_Lists__c);
        if (tempContact.Mailing_Lists__c == null) {
                tempContact.Mailing_Lists__c = 'RCC e-newsletter';
                system.debug('Passed ïf mailing_lists__c == null, set it to single value'); 
                }
        else {
            if (tempContact.Mailing_Lists__c.contains('RCC e-newsletter')) {
                        system.debug('Passed: if mailing_lists__c == RCC e-newsletter, returned null');
                return null;
                }
                else {tempContact.Mailing_Lists__c = tempContact.Mailing_Lists__c + '; RCC e-newsletter';
                system.debug('Just added ; RCC e-newsletter to Mailing_lists__c');                  
                }
            update tempContact;
            system.debug('Just updated tempContact'); 
            } // END ELSE                  
        } // end if contact
    else
    
    if (results[1] == 'Lead' ) {
        system.debug('starting SignUpNewsletter(), campmmbr.leadid is ' + campmmbr.leadid);
        Lead tempLead = [select id, mailing_lists__c from Lead where id = :results[0]];
        system.debug('Set templead to ' + templead.id);
        if (templead.Mailing_Lists__c == null) {
            templead.Mailing_Lists__c = 'RCC e-newsletter';
            system.debug('Just set templead.Mailing_Lists_c to RCC e-newsletter');
            }
        else {
            if (templead.Mailing_Lists__c.contains('RCC e-newsletter')) return null;
                else {templead.Mailing_Lists__c += '; RCC e-newsletter';}                
            }
            update tempLead;
        } // END if results[1] = Lead
            else {
                system.debug('In SignupNewsletter, didnt find contact or lead');
            }
    return null;
} // END SignUpNewsletter
   
public void SetOver18() {
    if (results[1] == 'Lead') {
        Lead tempLead = [select id, mailing_lists__c from Lead where id = :results[0]];
        tempLead.Over_18__c = true;
        update templead;        
    } // end if Lead
    else {
        tempContact = [select id, mailing_lists__c from Contact where id = :campmmbr.contactid ];
        tempContact.Over_18__c = true;
        update tempcontact;
    }
    return; 
}   
           
}
       //END CONTROLLER

 

bob_buzzardbob_buzzard

I think you are correct, in that you are adding the error to a different sobject instance.  When the pre-signup action method is invoked, you should locate the particular campaign in the mCampaign list rather than querying it from the database again.  While you are retrieving the same data, it is stored in a different object to those in the list.

Baird_SBaird_S

Thanks, let me mull this one over.  It seems like it's worth squeezing everything I can out of field-level error messages.  They're elegant and specific.

bob_buzzardbob_buzzard

That's definitely how I'd approach it.  Users tend to be able to resolve the errors faster if they are directed to the field, rather than having to read the error message and work out the erroneous data for themselves.  Let us know if you hit further issues,