Combine multiple objects within a list - salesforce

I'm looking to create a single list of records of various sObject types using apex to display to a custom visualforce page. I'm wondering if there is a way to combine multiple objects (case, opportunity, account, etc) within a single list. If not, how do you append the second object to the first in a list using visualforce code? Is there a best practice?
Thanks
So I could use a little more assistance completing this. I have written this:
public class MyController {
public List<ContactAndCase> ContactsAndCases { get; set; }
public Opportunity TheOpp{
get {
TheOpp = [select Id FROM Opportunity];
return TheOpp;
}
set;
}
public Case TheCase{
get {
TheCase = [select Id FROM Case];
return TheCase;
}
set;
}
}
How do I fill the ContactsAndCases List?

A VisualForce component iterates over a single list. The type of the List, e.g. List<Lead>, dictates what data can be rendered by a VF component.
In order to render Lists of different types, you can either have a separate VF component for each type, e.g.:
<apex:pageBlockTable value="{!contacts}" var="contact">
...
</apex:pageBlockTable>
<apex:pageBlockTable value="{!cases}" var="case">
...
</apex:pageBlockTable>
Or, you can create a new type which holds instances of the different types. Here's a controller example:
public class MyController {
public List<ContactAndCase> ContactsAndCases { get; set; }
public MyController() {
ContactsAndCases = new List<ContactAndCase>();
// populate ContactsAndCases list
}
public class ContactAndCase {
public Contact TheContact { get; set; }
public Case TheCase { get; set; }
}
}
Then, you can iterate over a List<ContactAndCase>:
<apex:pageBlockTable value="{!ContactsAndCases}" var="item">
<apex:column value="{!item.TheContact.LastName}" />
<apex:column value="{!item.TheCase.CaseNumber}" />
</apex:pageBlockTable>

Jeremy's wrapper class is what you want. In addition, you'll generate SOQL-based lists of the objects you want first and then loop through to create new wrapper instances for your wrapper list (ContactsAndCases in this case) containing values from both contacts and cases.

Maybe I am missing something but couldn't you simply collect them in:
List<SObject> objects = new List<SObject>();
You can then add any generic SObject into that list.

Related

Why can't I iterate through a list of a Wrapper class in Salesforce Visualforce?

I am trying to iterate through a list of records inside a wrapper class and show them on a Visualforce page. The custom object is called Campaign_Products__c, and the wrapper class is meant to show if the product has been selected by the user to add to a "cart".
Apex Controller code (extraneous bits removed):
public with sharing class CONTROLLER_Store {
...
public List<productOption> cpList { get; set; }
public class productOption {
public Campaign_Product__c product;
public Boolean inCart;
public Integer quantity;
}
...
public CONTROLLER_Store(){
...
List<Campaign> cmpList = getCampaignWithProducts(CampaignId,'');
// method above calls a campaign with a related list of Campaign Product records
if(cmpList.size() > 0){
cmp = cmpList[0];
cpList = new List<productOption>();
for(Campaign_Product__c pro : cmp.Campaign_Products__r){
productOption option = new productOption();
option.product = pro;
option.inCart = false;
option.quantity = 0;
cpList.add(option);
}
} else {
cmp = new Campaign();
CampaignId = null;
cpList = new List<productOption>();
}
....
}
Visualforce page (extraneous bits removed)
<apex:page controller="CONTROLLER_Store" >
<apex:repeat value="{! cpList }" var="option">
{!option.product.Product__r.Name}
<apex:inputCheckbox value="{! option.inCart }"/>
</apex:repeat>
</apex:page>
I get this error when trying to save the visualforce page:
Unknown property 'CONTROLLER_Store.productOption.product'
You need to make the properties in your wrapper visible to VF too. Something like
public class productOption {
public Campaign_Product__c product {get; private set};
public Boolean inCart {get; set};
public Integer quantity {get; set};
}
(assuming product should be readonly in VF). You need these access modifiers or full getter/setter methods.

Displaying Specific Fields from Facebook Graph API JSON

I'm trying to simply display the list of members in a specific group using the Facebook Graph API. I'm using Newtonsoft.JSON.
Here is the results of my url query:
Graph API Results
I used a JSON class generator and it gave me this:
public class Datum
{
public string name { get; set; }
public string id { get; set; }
public bool administrator { get; set; }
}
public class Cursors
{
public string before { get; set; }
public string after { get; set; }
}
public class Paging
{
public Cursors cursors { get; set; }
}
public class Members
{
public List<Datum> data { get; set; }
public Paging paging { get; set; }
}
public class RootObject
{
public Members members { get; set; }
public string id { get; set; }
}
I've tried every combination I can think of to display simply the list of members in a multi-line text box, but not sure if this is even the best way to display the list on a Windows Form App.
Could someone help me understand 2 things.
1) What is the best component to display the list of names in a Windows Form App?
2) What is the 1 or 2 lines to generate just the list of names using JsonConvert.DeserializeObject from this?
My raw data is stored in: string responseFromServer = reader.ReadToEnd();
To deserialize the JSON into your classes:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(responseFromServer);
To get the member names into a List<string>:
List<string> members = obj.members.data.Select(d => d.name).ToList();
Note: You need to have using System.Linq; at the top of your file in order to use the Select and ToList methods.
As far as displaying the data in a windows form app, there's not a "best" component-- it depends on what you're trying to accomplish as to what control you would choose to use. For example, if all you want to do is display the list of names in a multi-line textbox, you could do this:
textBox1.Text = string.Join("\r\n", members);
If you want to allow the user to be able to select individual names and do something based on that selection, you would probably want to use a ListBox or a ComboBox instead. You can populate a ListBox or ComboBox like this:
listBox1.DisplayMember = "name";
listBox1.DataSource = obj.members.data;
That should be enough to get you started.

Polulate dynamic control in angularjs

I've been developing a sample Single Page Web application using AngularJS + Asp.net Web API. I've been stuck at one point where I am not able to help my self, I've tried googling without any success.
My scenario is as following.
I've two entity 1)Car & 2)Dealer. I've one link table Car_Dealer. As per my sample scenario a specific car can be sold at multiple dealer. So my models at server side looks like below.
Car Model
namespace HelloWebAPI.Models
{
using System;
using System.Collections.Generic;
public partial class Car
{
public Car()
{
this.Car_Dealer = new HashSet<Car_Dealer>();
}
public int CarId { get; set; }
public string CarName { get; set; }
public string CarDetails { get; set; }
public virtual ICollection<Car_Dealer> Car_Dealer { get; set; }
}
}
Dealer Model
namespace HelloWebAPI.Models
{
using System;
using System.Collections.Generic;
public partial class Dealer
{
public Dealer()
{
this.Car_Dealer = new HashSet<Car_Dealer>();
}
public int DealerId { get; set; }
public string DealerName { get; set; }
public string DealerLocation { get; set; }
public virtual ICollection<Car_Dealer> Car_Dealer { get; set; }
}
}
Car Dealer Model
namespace HelloWebAPI.Models
{
using System;
using System.Collections.Generic;
public partial class Car_Dealer
{
public int Car_DealerId { get; set; }
public int CarId { get; set; }
public int DealerId { get; set; }
public virtual Car Car { get; set; }
public virtual Dealer Dealer { get; set; }
}
}
My server side controllers POST method is as below.
CarController.CS
public void Post(Car NewCar)
{
//to save the car data in the database.
Car NewCarObj = new Car();
NewCarObj.CarName = NewCar.CarName;
NewCarObj.CarDetails = NewCar.CarDetails;
objEntities.Cars.Add(NewCarObj);
foreach (Car_Dealer dealer in NewCar.Car_Dealer)
{
dealer.CarId = NewCarObj.CarId;
dealer.DealerId = NewCarObj.DealerId;
objEntities.Car_Dealers.Add(dealer);
objEntities.SaveChanges();
}
}
Code in App.js file is as below.
App.JS
var CreateCarCtrl = function ($scope, $location, Car, Dealer) {
$scope.items = Dealer.query({ q: $scope.query });
$scope.save = function () {
Car.save($scope.item);
$location.path('/CarListingScreen');
};
};
And this one is chunk of code from my template file that is AddCar.HTML
AddCar.HTML
<tr>
<td>
<label class="control-label" for="DealerName">Add Dealer</label>
</td>
<td>
<ul>
<li>
<select ng-model="item.DealerName">
<option ng-repeat="item in items">{{item.DealerName}}</option>
</select>
[<a href ng-click="items.splice($index, 1)">Remove</a>]
</li>
<li>[<a href ng-click="items.push({})">Add More</a>]
</li>
</ul>
</td>
</tr>
As we can see in Template file, I am trying to render the list of dealer in Drop Down list by two way binding as I am using the same template for Editing purpose also.
Hopefully you've got the scenario.
Now following are the questions for which I am looking for solutions
I should replace {{item.DealerName}} with something else so I can get that data back at server. What should be replaced ?
Neither Remove Nor Add More functionality is working. How can I make it functioning ?
How can I load data while editing the record ? I mean getting dealers filled in Dropdown & Creating number of dropdown accordingly to handle dealer ?
Please note here I can add more than one dealer so it should be handled in template also.
Edit
My form looks like below.
As we can see in screen shot user can add multiple dealers for specific car & Can remove added item also.
How to bind dropdown list of dealer as it's <Collection> of car dealer ?
How can I render Dropdown list dynamically while clicking Add More button & Getting this values back at server side?
Thanks a lot in advance.
There are still essential parts missing form your code so, i cannot answer all questions. But let me take a try
I should replace {{item.DealerName}} with something else so I can get
that data back at server. What should be replaced ?
The ng-model for this should be item.DealerId. When you post the complete car model it does not need to have the complete dealer object, just the Id should be enough. On the server you should get the dealer data based on your association before saving the car.
Neither Remove Nor Add More functionality is working. How can I make it functioning ?
I can tell remove is not working because the remove button is outside the ng-repeat and $index is not available outside, assuming you are trying Dealer to be removed by placing the remove button against each dealer. Try
<select ng-model="item.DealerName">
<option ng-repeat="item in items">{{item.DealerName}}</option>
[<a href ng-click="items.splice($index, 1)">Remove</a>]
</select>
For third point
How can I load data while editing the record ? I mean getting dealers
filled in Dropdown & Creating number of dropdown accordingly to handle
dealer ?
There should be a model on client side for list of dealers, which you can predefine or get it from server.
If the car has multiple dealers like Car.dealers, do a ng-repeat to render them
<div ng-repeat='dealer in Car.dealers'>
<select ng-model='dealer.id'ng-options='d.name for d in allDealers'>
</div>

How do I display the results of an aggregate SOQL query on a Visualforce page?

I'm very new to Visualforce.
I'm looking at this page here: http://force.siddheshkabe.co.in/2010/11/displaying-aggregate-result-on.html
So when I added this code onto a VisualForce page:
AggregateResult[] groupedResults = [SELECT Name, Days__c FROM Contact WHERE Days__c != ];
for (AggregateResult ar : groupedResults) {
System.debug('Name: ' + ar.get('Name') + '\nDays Taken : ' + ar.get('Days__c') + '\n');
But all it does is print the code instead of executing it. What should I be doing? Thanks for any guidance.
The Apex code goes into a custom controller or controller extension. The VisualForce page is a separate file from the controller. The page you referenced doesn't show the VF page. Also, I don't think you can bind VF components to AggregateResult, so you'll need a wrapper class.
Here's some working code.
Controller:
public with sharing class TestController {
public Summary[] Summaries { get; set; }
public TestController() {
AggregateResult[] results = [
SELECT Name, Count(Id) Quantity FROM Opportunity GROUP BY Name
];
Summaries = new List<Summary>();
for (AggregateResult ar : results) {
Summaries.add(new Summary(ar));
}
}
// wrapper class to hold aggregate data
public class Summary {
public Integer Quantity { get; private set; }
public String Name { get; private set; }
public Summary(AggregateResult ar) {
Quantity = (Integer) ar.get('Quantity');
Name = (String) ar.get('Name');
}
}
}
VF page:
<apex:page controller="TestController">
<apex:form >
<apex:repeat value="{!Summaries}" var="summary">
{!summary.Name}: {!summary.Quantity}<br/>
</apex:repeat>
</apex:form>
</apex:page>

How to get in a Visualforce page controller a value from a custom component controller?

I'm trying do develop a visualforce custom component which is an entity chooser. This custom component displays a UI which helps browsing some records. It's possible to select one record, and I'd like to get it from outside the component or its controller.
I've looked at the standard salesforce binding with assignTo bug it's not bidirectional...
Hope someone can help me..
Thanks
Are you passing an object into the component? Objects are passed by reference, so if your component has an attribute that takes an object and does something to it, your outer page controller will be able to access the changed values.
If you were to pass in a shell object, ie. if your UI is allowing a user to select an Account.
Class SelectedAccount
{
public Account theAccount {get;set;}
}
Component:
<apex:component controller="ComponentController">
<apex:attribute type="SelectedAccount" name="userSelectedAccount" description="Selected Account" assignTo="{!selectedAccount}"
</apex:component>
Component Controller:
public class ComponentController
{
public selectedAccount;
public void ComponentController(){}
public PageReference selectAccountFromUI(Account selected)
{
selectedAccount.theAccount = selected;
return null;
}
}
Page Using the Component:
<c:MyAccountComponent userSelectedAccount="{!instanceOfSelectedAccount}"/>
This would allow you to assign the user selected account into the instance of wrapper object which is owned by the outer controller. You can then reference:
instanceOfSelectedAccount.theAccount
from your main Visualforce Pages controller.
1 - Declare a static variable in the outside class (can be the VF page controller)
Something like :
public static apexType myRecordOutside;
2 -When you Make your choice from records in the method within the custom component controller
Do something like this :
OutsideClass.myRecordOutside = chosenRecord; //notice that when its static you can access it without instantiating the outside class.
3- then, declare in your Visual force
<c:myCustomComponent userSelectedAccount = {!myRecordOutside}></c:myCustomComponent>
this will get myRecordOutside not from the component's controller class, but from the outside class
If you have any question about a part of my answer let me know :)
/* This is an example of getting non static variable value
from visualforce component controller variable to visualforce page controller variable */
VF page: DisplayCountryPage
<apex:page>
<apex:commandButton value="display country list" action="{!displaycountryname}" />
<apex:repeat value="{!displaycountrylistvalue}" var="item">
<div>
{!item}
</div>
</apex:repeat>
<c:testvfcmp vfpageclasscontroller="{!thisPageInstance}"/>
</apex:page>
=====================
DisplayCountryPage VF Page controller: vfpageclass
public class vfpageclass{
public List<String> displaycountrylistvalue{get;set;}
public vfcomponentclass vfcmpobj{get;set;}
public void methodtosetvfcomponentclass(vfcomponentclass vfcmpobj2){
vfcmpobj = vfcmpobj2;
}
public void displaycountryname(){
displaycountrylistvalue = new List<String>();
displaycountrylistvalue = vfcmpobj.listOfCountry;
}
public vfpageclass thisPageInstance{
get{
return this;
}
set;
}
}
======================
vf component: testvfcmp
create an attribute like below:
<apex:component controller="CSTSearchPanelController">
<apex:attribute name="vfpageclasscontroller"
type="vfpageclass"
assignTo="{!vfpageobj}"
description="The controller for the page." />
<apex:commandButton value="set country list" action="{!setCountrylist}" />
</apex:component>
=====================
<testvfcmp> vf component controller: vfcomponentclass
public class vfcomponentclass{
public List<String> listOfCountry = new List<String>();
public vfpageclass vfpageobj{
get;
set{
vfpageobj = value;
vfpageobj.methodtosetvfcomponentclass(this);
}
}
public void setCountrylist(){
listOfCountry.add('India');
listOfCountry.add('USA');
}
}
/* This is an example of getting static variable value
from visualforce component controller variable to visualforce page controller variable */
VF page: DisplayCountryPage
<apex:page>
<apex:commandButton value="display country list" action="{!displaycountryname}" />
<apex:repeat value="{!displaycountrylistvalue}" var="item">
<div>
{!item}
</div>
</apex:repeat>
<c:testvfcmp vfpageclasscontroller="{!thisPageInstance}"/>
</apex:page>
=====================
DisplayCountryPage VF Page controller: vfpageclass
public class vfpageclass{
public List<String> displaycountrylistvalue{get;set;}
public void methodtosetvfcomponentclass(vfcomponentclass vfcmpobj2){
if(vfcmpobj2.getStaticCountryList() !=null){
displaycountrylistvalue = new List<String>();
displaycountrylistvalue = vfcmpobj2.getStaticCountryList();
}
/* USE THIS displaycountrylistvalue VARIABLE THROUGHOUT THE CLASS ONCE YOU SET BY HITTING BUTTON <set country list>.
DO NOT USE vfcmpobj2.getStaticCountryList() IN OTHER METHODS TO GET THE VALUE, IF DO, IT WILL RETURN NULL*/
}
public void displaycountryname(){
}
public vfpageclass thisPageInstance{
get{
return this;
}
set;
}
}
======================
vf component: testvfcmp
create an attribute like below:
<apex:component controller="CSTSearchPanelController">
<apex:attribute name="vfpageclasscontroller"
type="vfpageclass"
assignTo="{!vfpageobj}"
description="The controller for the page." />
<apex:commandButton value="set country list" action="{!setCountrylist}" />
</apex:component>
=====================
<testvfcmp> vf component controller: vfcomponentclass
public class vfcomponentclass{
public static List<String> listOfCountry = new List<String>();
public vfpageclass vfpageobj{
get;
set{
vfpageobj = value;
vfpageobj.methodtosetvfcomponentclass(this);
}
}
public static void setCountrylist(){
listOfCountry.add('India');
listOfCountry.add('USA');
}
public List<String> getStaticCountryList(){
return listOfCountry;
}
}

Resources