+ Start a Discussion
TehNrdTehNrd 

Creating a dataTable with fields that are not in the given sObect?

Is it possible to create a dataTable that contains fields that are not in the sObject of the dataTable. Perhaps a check box or a picklist or both. This question sort of stems from this thread, http://community.salesforce.com/sforce/board/message?board.id=Visualforce&thread.id=691 ,  which to be honest I haven't totally understood.

Here is a real use case that we are looking at addressing with Visual Force. We would like to pull a list of contacts and do mass emailing using Apex Email services. Essentially we would pull a list of contacts and put this in a dataTable but on the left side of the dataTable there would check boxes that indicate if we would like to send this user an email. There would also be another column that is a picklist which determines what type email they should receive.  A user would then make their selections and hit the send email button.

Neither of these fields are on the contact as they would only be relevant for this VF page. So is it possible to build something like this where the checkbox and and picklist value are passed to a collection of contacts?

Here is what I have so far. I know its not right as all of the checkboxes and picklist are pointing to the same variable but I think it gives you an idea of what we are trying to do.
Page:
Code:
<apex:page controller="contacts">
        <apex:panelGrid columns="1" id="theGrid" width="50%" >
        <apex:pageBlock>
        <apex:form>
        <apex:dataTable value="{!Contacts}" var="con" styleClass="list">
                <apex:column>
                        <apex:facet name="header"><apex:inputCheckbox/></apex:facet>
                        <apex:inputCheckbox/>
                </apex:column>
                <apex:column>
                        <apex:facet name="header">Name</apex:facet>
                        <apex:outputText value="{!con.Name}"/>
                </apex:column>
                <apex:column>
                        <apex:facet name="header">Phone</apex:facet>
                        <apex:outputText value="{!con.Phone}"/>
                </apex:column>
                <apex:column>
                        <apex:facet name="header">Mailing City</apex:facet>
                        <apex:outputText value="{!con.MailingCity}"/>
                </apex:column>
                <apex:column>
                        <apex:facet name="header">Email</apex:facet>
                        <apex:outputText value="{!con.Email}"/>
                </apex:column>
                <apex:column>
                        <apex:facet name="header">Email Type</apex:facet>
                        <apex:selectList value="{!emailType}" size='1'>
                                <apex:selectOptions value="{!emails}"/>
                        </apex:selectList>
                </apex:column>
        </apex:dataTable>
        </apex:form>
        </apex:pageBlock> 
        </apex:panelGrid>
</apex:page>

Controller:
Code:
public class contacts {
    
        Contact [] Contacts;
        String emailType;
        
        public List<Contact> getContacts(){
                if(contacts == null){
                        contacts = [select Id, Name, Phone, MailingCity, Email from Contact limit 10];
                } 
                return Contacts;
        }

        public void setemailType(String emailType){
                this.emailType= emailType;
        }

        public List<SelectOption> getEmails(){
                List<SelectOption> options = new List<SelectOption>();
                
                options.add(new SelectOption('','-None-'));
                options.add(new SelectOption('Renewal Notice','Renewal Notice'));
                options.add(new SelectOption('White Paper','White Paper'));
                options.add(new SelectOption('Phone Call Follow Up','Phone Call Follow Up'));
                              
                return options;
           
        }

 public String getEmailType() {
        return emailType;
     }
}

 


Ron HessRon Hess
I've modified your code to demonstrate the concept;

Simply said, make a new class which holds your sobject and any data related to that sobject.
Then make an array of those, adding getters and setters to the new inner class.

Now the source code:

First the controller, note the new class mContact{} holds a single contact and the boolean and picklist associated to it.
Also has a handy constructor.


Code:
public class contacts {
    public class mcontact { 
  contact c; string emailType; boolean selected; 
  
  public String getEmailType() {
      return emailType;
  }
  public void setemailType(String emailType){
      this.emailType= emailType;
  }
  public mcontact( contact con) { c=con;}
  public Contact getContact() { return c; }
  
  public boolean getSelected() { return selected; }
  public void setSelected(boolean sb) { selected = sb; }
  
  public List<SelectOption> getEmails(){
   List<SelectOption> options = new List<SelectOption>();
   options.add(new SelectOption('','-None-'));
   options.add(new SelectOption('Renewal Notice','Renewal Notice'));
   options.add(new SelectOption('White Paper','White Paper'));
   options.add(new SelectOption('Phone Call Follow Up','Phone Call Follow Up'));
   return options; 
  }
 } 
    
    mContact [] Contacts;

    public List<mContact> getContacts(){
        if(contacts == null){
         contacts = new mContact[]{};
            for( Contact c: [select Id, Name, Phone, MailingCity, Email from Contact limit 10]) {
             contacts.add( new mContact(c) );  
            }    
        } 
        return Contacts;
    }
}

 


now, the VF Page with modified values, not a big change, your page was just fine.

Code:
<apex:page controller="contacts">
<apex:panelGrid columns="1" id="theGrid" width="50%" >
<apex:pageBlock>
<apex:form>
<apex:dataTable value="{!Contacts}" var="con" styleClass="list">
<apex:column>
<apex:facet name="header">
<apex:inputCheckbox/>
</apex:facet>
<apex:inputCheckbox value="{!con.selected}" />
</apex:column>
<apex:column headerValue="Name">
<apex:outputText value="{!con.contact.Name}"/>
</apex:column>
<apex:column headerValue="Phone">
<apex:outputText value="{!con.contact.Phone}"/>
</apex:column>
<apex:column headerValue="Mailing City">
<apex:outputText value="{!con.contact.MailingCity}"/>
</apex:column>
<apex:column headerValue="Email">
<apex:outputText value="{!con.contact.Email}"/>
</apex:column>
<apex:column headerValue="Email Type">
<apex:selectList value="{!con.emailType}" size='1'>
<apex:selectOptions value="{!con.emails}"/>
</apex:selectList>
</apex:column>
</apex:dataTable>
</apex:form>
</apex:pageBlock>
</apex:panelGrid>
</apex:page>

 



Message Edited by dchasman on 01-16-2009 11:14 AM
TehNrdTehNrd
GENIUS!!!!

Thanks Ron! This was incredibly helpful.

It appears that using this process you could literally create any type of "sObject" even if it doesn't exist in your schema to hold data from many different objects, pass that to the dataTable and then process it anyway you want with an action.

This is great. Just the Visual Force jump start I needed. Thanks again.

-Jason
Steve ChadbournSteve Chadbourn
I'm a bit confused about the difference between member variables and instance variables and how to use them in the getter and setters. I come from a C# background so this may be obvious to java people.
 
In Ron's example above there are is String member variable called emailType and a boolean member variable called selected. In the setter for emailType you prefix the variable name with "this" but not in the setter for selected. I thought that this refered to the instance variable? Is this something you have to do with Strings?
 
 
Ron HessRon Hess
setters set the value in the instance of the class
In setSelected, yes i should have use this , however it's implied so both are correct
public void setSelected(boolean sb) { this.selected = sb; }

selected is a class member of the same class this method is defined in, so "this" resolves to the nearest class namespace.
ShriramShriram

Hi,

My requirement was also similar as explained in the post. I have a dataTable with checkbox for each row.

I get a list of contacts for account and display them in VF page with a button with a checkbox for each row.

When a user selects n number of checkbox and click on the button in VF page, how do I know which are the checkboxes that the user had checked. I need to get the ID related to the each contact that is checked and perform a mass update.

How do i do that ? Any sample code with the same example as discussed in this post would help me a lot.

Thanks in advance.....

 

dmchengdmcheng

Ron, thanks so much for posting this.  One thing I don't understand - are the lower case and upper case "contacts" supposed to be different objects, or are they the same object?
 

I tried translating your example into my own situation but I get an error when I save my VF page: "unknown property ListOfPeople: ppl"  Can you tell me where I've gone wrong?  Thanks.

 

Controller:

 

public class ListOfPeople {
public class metaPerson {
Person__c p; Boolean selected;

public metaPerson(Person__c person) { p = person;}
public Person__c getPerson() { return p; }

public Boolean getSelected() { return selected; }
public void setSelected(Boolean sb) { selected = sb; }
}

metaPerson[] ppl;

public List<metaPerson> getPersons(){
if(ppl == null){
ppl = new metaPerson[]{};
for( Person__c p : [select Id, Name, Primary_Email__c from Person__c limit 10]) {
ppl.add(new metaPerson(p));
}
}
return ppl;
}

}

 

 

 

 VF page:

 

public class ListOfPeople {
public class metaPerson {
Person__c p; Boolean selected;

public metaPerson(Person__c person) { p = person;}
public Person__c getPerson() { return p; }

public Boolean getSelected() { return selected; }
public void setSelected(Boolean sb) { selected = sb; }
}

metaPerson[] ppl;

public List<metaPerson> getPersons(){
if(ppl == null){
ppl = new metaPerson[]{};
for( Person__c p : [select Id, Name, Primary_Email__c from Person__c limit 10]) {
ppl.add(new metaPerson(p));
}
}
return ppl;
}

}

 

 

 

Message Edited by dmcheng on 03-24-2010 12:16 PM
Baird_SBaird_S

Ron, this is elegant.  Thanks so much.  Makes me feel like a pro to be able to insert this code for my clients.