+ Start a Discussion
vviyervviyer 

Simple VF Wizard problem

Hi

Im a novice in VF and coding. Im writing a simple wizard for the Volunteer Management App. Add event info in step1, then click 'add participants" to go to participants to add participants.SFDC_Volunteer_Event__c (master) and SFDC_Volunteer_Participant__c(detail) are the objects. I have done this with a custom controller to replace the Events tab and it works!.

However, since I want to use the VF page to replace the "new" button, I need to use the standard controller and write an extension(right?).

 

2 VF pages VMXpage1, VMXPage2. 1 extension VMExtension.cls

Currently, I have only setup step 2, to add ONE participant, but I would like to extend it to add (like 'add row?". need inputs on how to do that too). but primarily, Im getting the error

 

Visualforce Page: /apex/VMXPage1

System.TypeException: Invalid conversion from runtime type SOBJECT:SFDC_Volunteer_Event__c to SOBJECT:SFDC_Volunteer_Participant__c

Class.VMExtension.<init>: line 9, column 21
External entry point

 

 

------------

Here is the code




public class VMExtension{

SFDC_Volunteer_Event__c vevent;

SFDC_Volunteer_Participant__c vpart1;

public VMExtension(ApexPages.StandardController stdController){
this.vevent=(SFDC_Volunteer_Event__c)stdController.getRecord();
this.vpart1=(SFDC_Volunteer_Participant__c)stdController.getRecord();
}


public PageReference event(){
return Page.VMXPage1;
}

public PageReference addparts(){
return Page.VMXPage2;
}

public PageReference saveevent(){
insert vevent;
vpart1.Volunteer_Event__c=vevent.id;
insert vpart1;
PageReference veventPage = new PageReference('/'+vevent.id);
veventPage.setRedirect(true);
return veventPage;
}
}
------
Here is the VF page

<apex:page standardController="SFDC_Volunteer_Event__c" extensions="VMExtension">

<apex:sectionHeader title="New Event Information" subtitle="step 1/2"/>

<apex:form id="theform">
<apex:pageBlock >
<apex:pageBlockButtons location="bottom">
<apex:commandButton value=" Save Event" action="{!saveevent}"/>
<apex:commandButton value="Add Participants" action="{!addparts}"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
<apex:pageBlockSection title="Event Information" columns="2">
<apex:inputField value="{!SFDC_Volunteer_Event__c.name}" required="true"/>
</apex:pageBlockSection>
</apex:pageBlock>
</apex:form>

</apex:page>


---
<apex:page standardController="SFDC_Volunteer_Participant__c" extensions="VMExtension">
<apex:sectionHeader title="Add Participants to Event:" subtitle="step 2/2"/>
<apex:form id="AddParticipantForm">
<apex:pageBLock >
<apex:pageBlockSection >
<apex:panelGrid columns="2">
<apex:outputLabel value="Contact1"/>
<apex:inputField value="{!SFDC_Volunteer_Participant__c.Contact__c}"/>


</apex:panelGrid>
</apex:pageBlockSection>
<apex:pageBlockButtons location="bottom">
<apex:commandButton action="{!event}" value="Edit Event Info"/>
<apex:commandButton action="{!saveevent}" value="Save Event"/>
<apex:commandButton value="Cancel" action="{!cancel}"/>
</apex:pageBlockButtons>
</apex:pageBLock>
</apex:form>

</apex:page>
------

 

Im stuck. Please help. Thank you in advance

 

Message Edited by vviyer on 03-31-2009 05:40 PM
Message Edited by vviyer on 03-31-2009 05:41 PM
Best Answer chosen by Admin (Salesforce Developers) 
CarcajouCarcajou

Hi,

 

i am very sorry, i introduced 2 bugs, the partRendered needs to be public as it is accessed from outside, this is the same for the object SFDC_Volunteer_Participant__c vpart1.

Additionally, the VF page should refer to vpart1 and not to SFDC_Volunteer_Participant__c.

here is the code adjusted :

 

<apex:page standardController="SFDC_Volunteer_Event__c" extensions="VMExtension"> <apex:sectionHeader title="New Event Information" /> <apex:form id="theform"> <apex:pageBlock > <apex:pageBlockButtons location="bottom"> <apex:commandButton value=" Save Event" action="{!saveevent}"/> <apex:commandButton value="Add Participants" action="{!addparts}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection title="Event Information" columns="2"> <apex:inputField value="{!SFDC_Volunteer_Event__c.name}" required="true"/> </apex:pageBlockSection> </apex:pageBlock> <apex:pageBlock rendered="{!partRendered}"> <apex:pageBlockSection> <apex:panelGrid columns="2"> <apex:outputLabel value="Contact1"/> <apex:inputField value="{!vpart1.Contact__c}"/> </apex:panelGrid> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>

and

 

 

public class VMExtension{ SFDC_Volunteer_Event__c vevent; public SFDC_Volunteer_Participant__c vpart1 {get; set;} public Boolean partRendered {get; set;} public VMExtension(ApexPages.StandardController stdController){ this.vevent=(SFDC_Volunteer_Event__c)stdController.getRecord(); partRendered = false; } public PageReference event(){ return Page.VMXPage1; } public PageReference addparts(){ partRendered = true; return null; } public PageReference saveevent(){ insert vevent; vpart1 = new SFDC_Volunteer_Participant__c(); vpart1.Volunteer_Event__c=vevent.id; insert vpart1; PageReference veventPage = new PageReference('/'+vevent.id); veventPage.setRedirect(true); return veventPage; } public PageReference cancel(){ return null; }

}

 

It should work now.

Catherin.

All Answers

CarcajouCarcajou

Hi,

 

I think an extension can only apply to one standard or custom controller. You cannot have the same extension for 2 pages having 2 different standard controllers.  

In your specific case, i think the easiest is to build one single page with a custom controller and maybe hide or unhide the part of the page containing the participants. 

 

Hope this helps. 

Catherin. 

vviyervviyer

Oh ok. Thank you for that info. I was under the impression that a VF page can reuse a extension. Thats the reason for writing classes right?The reason I wanted to use an extension is so that I can have the standard button "New" point to this wizard.

 

What would be the best way to do this? 

CarcajouCarcajou

Hi,

 

You can override the "New" button with a visualforce page. If you go to

App Setup>Create>Objects>your object

there is a section Standard button and in front of the New button there is a link "override". Then you will see you can provide a VF page.

 

Kind Regards,

Catherin.

vviyervviyer
Yes you can override. But only with a VF Page which uses a "STANDARD CONTROLLER". I cannot use a custom controller. Hence teh need for a extension to the standar controller
CarcajouCarcajou

Hi,

 

yes, i understand now your problem. But in that case i would just build one single page : 

 

<apex:page standardController="SFDC_Volunteer_Event__c" extensions="VMExtension"> <apex:sectionHeader title="New Event Information" /> <apex:form id="theform"> <apex:pageBlock > <apex:pageBlockButtons location="bottom"> <apex:commandButton value=" Save Event" action="{!saveevent}"/> <apex:commandButton value="Add Participants" action="{!addparts}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection title="Event Information" columns="2"> <apex:inputField value="{!SFDC_Volunteer_Event__c.name}" required="true"/> </apex:pageBlockSection> </apex:pageBlock> <apex:pageBlock rendered="{!partRendered}"> <apex:pageBlockSection> <apex:panelGrid columns="2"> <apex:outputLabel value="Contact1"/> <apex:inputField value="{!SFDC_Volunteer_Participant__c.Contact__c}"/> </apex:panelGrid> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>

  with the extension as :

 

 

public class VMExtension{ SFDC_Volunteer_Event__c vevent; SFDC_Volunteer_Participant__c vpart1; Boolean partRendered {get; set;} public VMExtension(ApexPages.StandardController stdController){ this.vevent=(SFDC_Volunteer_Event__c)stdController.getRecord(); partRendered = false; } public PageReference event(){ return Page.VMXPage1; } public PageReference addparts(){ partRendered = true; return null; } public PageReference saveevent(){ insert vevent; vpart1 = new SFDC_Volunteer_Participant__c(); vpart1.Volunteer_Event__c=vevent.id; insert vpart1; PageReference veventPage = new PageReference('/'+vevent.id); veventPage.setRedirect(true); return veventPage; } public PageReference cancel(){ return null; } }

 

 

 

 If you want to create 2 pages, you will need 2 extensions.

 

Kind Regards, 

Catherin. 

 

vviyervviyer

I took your suggestion and changed the code. I'm getting this error

Save error: Unknown property 'SFDC_Volunteer_Event__cStandardController.partRendered'   

Save error: Unknown property 'SFDC_Volunteer_Event__cStandardController.SFDC_Volunteer_Participant__c'    

 

It looks like the page is unable to find the partRendered variable.

CarcajouCarcajou

Hi,

 

i am very sorry, i introduced 2 bugs, the partRendered needs to be public as it is accessed from outside, this is the same for the object SFDC_Volunteer_Participant__c vpart1.

Additionally, the VF page should refer to vpart1 and not to SFDC_Volunteer_Participant__c.

here is the code adjusted :

 

<apex:page standardController="SFDC_Volunteer_Event__c" extensions="VMExtension"> <apex:sectionHeader title="New Event Information" /> <apex:form id="theform"> <apex:pageBlock > <apex:pageBlockButtons location="bottom"> <apex:commandButton value=" Save Event" action="{!saveevent}"/> <apex:commandButton value="Add Participants" action="{!addparts}"/> <apex:commandButton value="Cancel" action="{!cancel}"/> </apex:pageBlockButtons> <apex:pageBlockSection title="Event Information" columns="2"> <apex:inputField value="{!SFDC_Volunteer_Event__c.name}" required="true"/> </apex:pageBlockSection> </apex:pageBlock> <apex:pageBlock rendered="{!partRendered}"> <apex:pageBlockSection> <apex:panelGrid columns="2"> <apex:outputLabel value="Contact1"/> <apex:inputField value="{!vpart1.Contact__c}"/> </apex:panelGrid> </apex:pageBlockSection> </apex:pageBlock> </apex:form> </apex:page>

and

 

 

public class VMExtension{ SFDC_Volunteer_Event__c vevent; public SFDC_Volunteer_Participant__c vpart1 {get; set;} public Boolean partRendered {get; set;} public VMExtension(ApexPages.StandardController stdController){ this.vevent=(SFDC_Volunteer_Event__c)stdController.getRecord(); partRendered = false; } public PageReference event(){ return Page.VMXPage1; } public PageReference addparts(){ partRendered = true; return null; } public PageReference saveevent(){ insert vevent; vpart1 = new SFDC_Volunteer_Participant__c(); vpart1.Volunteer_Event__c=vevent.id; insert vpart1; PageReference veventPage = new PageReference('/'+vevent.id); veventPage.setRedirect(true); return veventPage; } public PageReference cancel(){ return null; }

}

 

It should work now.

Catherin.

This was selected as the best answer
vviyervviyer

This totally worked :). I had to instantiate the participant as below, otherwise it would insert null values.

 

public SFDC_Volunteer_Participant__c vpart1 {
        get {
            if(vpart1==null)
            vpart1=new SFDC_Volunteer_Participant__c();
        return vpart1;
        }
        set;
    }

 

Could you explain the logic behind using the sObject name for event in the VF page, and using the variable (vPart1) for Participant in  the VFPage.

 

I really appreciate your patience with me. If you get a chance plz go to http://community.salesforce.com/sforce/board/message?board.id=Visualforce&thread.id=11593 I had another question :(

Message Edited by vviyer on 04-01-2009 11:47 PM
CarcajouCarcajou

great !!

 

in fact as you use a standard controller on the object SFDC_Volunteer_Event__c, you can directly use the name of this object to access any of its field in the VF page.

But if you need to access fields from another object, you need an extension in which you define the object you want to access :

public SFDC_Volunteer_Participant__c vpart1 {get; set;}