Using Apex Repeat to Populate a Visualforce Table - salesforce

It appears that my List is blank, not being passed through with the controller extension or otherwise some problem is causing my table not to populate the anticipated data. This visualforce page is being loaded from a custom button on a Work Order.
I've tried populating the data by using:
:ApexPages.CurrentPage().getParameters().get('id')
As well as just hardcoding what I believe is the 'id' as shown in the code example.
The VF Page is as follows:
<apex:page Standardcontroller="WorkOrder" extensions="cWOInvoice1" renderAs="pdf">
<apex:form >
...
<table style="...">
<tbody style="...">
<tr style="display:table-row;">
<th style="...">Scope of Work</th>
<th style="...">Trade</th>
<th style="...">Price</th>
</tr>
<apex:repeat value="{!woli}" var="woli">
<tr>
<td style = "...">{!woli.Repair_Product__r.Name}</td>
<td style = "...">{!woli.Repair_Product__r.Trade__c}</td>
<td style = "...">${!woli.Item_Price_Roll_Up_Sub__c}</td>
</tr>
</apex:repeat>
</tbody>
</table>
...
</body>
</apex:form>
</apex:page>
The controller looks like this (Again hardcoded workOrderID for bugtesting):
public class cWOInvoice1 {
public WorkOrderLineItem woli {get;set;}
public cWOInvoice1(ApexPages.StandardController controller){
List<WorkOrderLineItem>woli=[SELECT Id, Area__c, Tenant_Responsible__c, WorkOrderId, Repair_Product__r.Name, Repair_Product__r.Bill_Rate_Retail__c, Repair_Product__r.Bill_Rate__c, Repair_Product__r.Trade__c FROM WorkOrderLineItem WHERE WorkOrderId='0WO55000000Cw4LGAS'];
}
}
I expected the custom controller to pass through a list of work order line items that apex repeat would then display in the table. Instead, I get an empty table.

You have the variable woli declared with two different types in different scopes.
At the controller level, woli is a single WorkOrderLineItem member variable:
public WorkOrderLineItem woli {get;set;}
Because it's never initialized, its value is null.
Inside your constructor, you re-declare woli as a List<WorkOrderLineItem> and initialize it:
public cWOInvoice1(ApexPages.StandardController controller){
List<WorkOrderLineItem>woli=[SELECT Id, Area__c, Tenant_Responsible__c, WorkOrderId, Repair_Product__r.Name, Repair_Product__r.Bill_Rate_Retail__c, Repair_Product__r.Bill_Rate__c, Repair_Product__r.Trade__c FROM WorkOrderLineItem WHERE WorkOrderId='0WO55000000Cw4LGAS'];
}
This value goes out of scope at the end of the constructor and is never made available to your page.
You need to remove the local declaration and correct the type of the member variable.
Whether or not your <apex:repeat> currently compiles (I'm not sure if that's legal or not off the top of my head), you should change your iteration variable to have a different name than the bound property:
<apex:repeat value="{!woli}" var="woli">
You may wish to make the controller property something like woliList to clarify.

Related

Unknown Property Error using Custom Controller in Visualforce

I have an error with a new Visualforce page I'm creating that takes list from a custom controller I made. It is for a standard objects and the class file compiled just fine. But when I start building the Visualforce page it gives me an error that I can't figure out.
This is the Visual Force Page
<apex:page controller="SearchAccountListController">
<apex:repeat value="{! acctList}" var="acct">
<apex:outputLink value="/{!acct.Name}">
<apex:outputText value="{!acct.Phone}"/><br/>
</apex:outputLink>
</apex:repeat>
</apex:page>
And the Controller:
public class SearchAccountListController {
public List<Account> getNewAccounts() {
List<Account> acctList = [SELECT Name,Phone FROM Account];
return acctList;
}
}
The class compiles fine, I'm using the Developer Console, so that seems to be okay. But then when I go to save my Visualforce page it gives the following error:
Save error: Unknown property 'Unknown property 'SearchAccountListController.acctList'
You don't have a class-level property acctList, you only have a local variable with that name. That name is lost when you leave the function.
From visualforce's point of view you have a getter function and what it returns can be accessed with {!newAccounts}.

Displaying Records based on keyword from vf page

I have a senario where i will be dispalying input text fieldon vf page ,when i enter some value and click on search button the realted accounts should be displayed depending on that keyword.
I have tried the following code ,but i am unable to resolve the error Unknown property 'VisualforceArrayList.Name'
The below is my code:
class:
public class AccountswithKeywordfrompage {
public string keyword{get;set;}
public List<List<Account>> accountlist{get;set;}
public void Accounts(){
keyword = System.currentPageReference().getParameters().get('search');
accountlist=[FIND '+keyword' IN ALL FIELDS
RETURNING Account(Name)];
}
}
vf page:
<apex:page controller="AccountswithKeywordfrompage" standardStylesheets="false">
<apex:form>
<apex:inputText label="SearchAccounts" id="search">
<apex:commandButton value="search" action="{!Accounts}"/>
</apex:inputText>
<apex:pageblock>
<apex:pageblockTable value="{!accountlist}" var="accountobj">
<apex:outputlink value="{!accountobj.Name}"/>
</apex:pageblockTable>
</apex:pageblock>
</apex:form>
</apex:page>
Can anyone help me to solve the issue ?
accountlist is a List<List<Account>>, which is the wrong type; a SOSL search returns a List<List<sObject>>. It just so happens that your SOSL search only returns Account results.
When you iterate over a List<List<sObject>>:
<apex:pageblockTable value="{!accountlist}" var="accountobj">
the type of the iteration variable is List<Account>, which has no Name property.
The cleanest solution is to declare your variable as a List<Account> and extract the first element of the returned List<List<sObject>> from SOSL.

Visualforce page not rendering values from controller

Need your inputs in a scenario I am currently stuck in. Here are the details. Appreciate your time and all your inputs.
currently I am able to see the values retrieved in controller but they are not being displayed on visualforce page.
Requirement: I need to email bulk of selected contacts. When there is no email to selected contacts, we are required to populate the name of contacts on UI who do not have the email. I am able to accomplish first part of requirement but stuck on displaying contact names on visual force page .
List button : BulkEmailTest which calls firstVF visual force page.
firstVF code:
<apex:page standardController="Contact" extensions="FirstController" recordSetVar="listRecs"
action="{!send}">
Emails are being sent!
<script> window.history.back();
</script>
</apex:page>
FirstController code: for simplified code, I have edited snippet for contacts with email as our priority is only related to contacts with no email.
public with sharing class FirstController
{
public List<Contact> noEmail {get;set;}
public Contact contact;
public List<Contact> allcontact {get; set;}
Id test;
public Contact getAllContact() {
return contact;
}
ApexPages.StandardSetController setCon;
ApexPages.StandardController setCon1;
public static Boolean err{get;set;}
public FirstController(ApexPages.StandardController controller)
{
setCon1 = controller;
}
public FirstController(ApexPages.StandardSetController controller)
{
setCon = controller;
}
public PageReference cancel()
{
return null;
}
public FirstController()
{
}
public PageReference send()
{
noEmail = new List<Contact>();
set<id> ids = new set<id>();
for(Integer i=0;i<setCon.getSelected().size();i++){
ids.add(setCon.getSelected()[i].id);
}
if(ids.size() == 0){
err = true;
return null;
}
List<Contact> allcontact = [select Email, Name, firstName , LastName from Contact where Id IN :ids];
for(Contact current : allcontact)
{
system.debug(current);
if (current.Email!= null)
{
PageReference pdf = Page.pdfTest;
pdf.getParameters().put('id',(String)current.id);
system.debug('id is :'+current.id);
pdf.setRedirect(true);
return pdf;
}
else //No email
{
system.debug('in else current'+current );
noEmail.add(current);
// noEmail.add(current);
system.debug('in else noemail'+noEmail );
}//e
}
if(noEmail.size()>0 ) {
PageReference pdf1 = Page.NoEmailVF;
pdf1.getParameters().put('Name', String.valueOf(noEmail));
system.debug('pring noEmail' +noEmail);
pdf1.setRedirect(false);
return pdf1;
}
return null;
}
}
NoEmailVF visual force page code
<apex:page controller="FirstController">
<b> Emails are not sent to below contacts :
<table border="1">
<tr>
<th>Name</th>
</tr>
<apex:repeat var="cx" value="{!allcontact}" rendered="true">
<tr>
<td>{!cx.name}</td>
</tr>
</apex:repeat>
</table>
<p> Please note that emails are not sent to selected Donors only when
they did not make any donation for that year or if they do not have email address listed. </p>
<p>If you still wish to retrieve donations made in this year, then you may use "Hard Copy" button listed on the Donor record to have the data printed. </p>
</b>
<apex:form >
<apex:commandButton action="{!cancel}" value="Back" immediate="true"/>.
</apex:form>
</apex:page>
It's bit messy. I think I know why it doesn't work but I'm also going to give you few tips how to clean it up.
I don't think you need 2 separate pages. You could do it on 1 page. I'm not even sure what were you trying to accomplish. Should the user be moved to previous page (some listview button I guess? Wherever history.back() takes them). Or to Page.NoEmailVF. (and there's even Page.pdfTest thrown into the mix ;))
If you're sure you need multiple pages - here's how you can transfer "state" of the controller across pages. It should work automatically as long as they share same controller (or extension), no need to pass anything via url: https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_quick_start_wizard.htm
Your constructors don't do much. They save the references to standard(set)controller but they don't run any queries. Contacts aren't queried until the send() method.
You're hoping to pass the noEmail parameter with String.valueOf(List<Contact>). It's... uh.. it probably does something but after redirect you don't read anything. The NoEmailVF page has just <apex:page controller=... (not an extension) so the FirstController() (the one without any parameters) is called. And it has empty body! It completely ignores what was passed via url. It probably could read what you passed using ApexPages.currentPage().getParameters().get('Name') but then honestly no idea what you can do to create real list of contacts out of such string. Messy. You probably could do some JSON.serialize and then deserialize but I don't like the whole idea.
And last but not least - calling page action is evil, unexpected for the user and against salesforce security best practices. Pls check my old answer https://salesforce.stackexchange.com/a/28853/799
So...
What a random internet stranger thinks you need:
1 VF page. With only 1 constructor, the one that takes StandardSetController.
In the constructor inspect the ssc.getSelected() and query SELECT Id, Name FROM Contact WHERE Id IN :ssc.getSelected() AND Email = null. Save the results of the query into public contactsWithoutEmail {get; private set;}
Do NOT have the action={!send} unless you absolutely need it automated. it should be conscious user's decision to click some final "Do it!" button.
In the send() method query only these SELECT Id, Name FROM Contact WHERE Id IN :ssc.getSelected() AND Email != null and process them.
In visualforce - use <apex:pageBlockTable>, <apex:dataTable> or similar to display contactsWithoutEmail. No need to hand-craft the html.
And I recommend making send a normal apex:commandButton, not action

Visualforce Page List output

How do you print out a custom Apex class list, that is not related to an Sobject? I keep getting error of
Error: Unknown property 'apiMyIntegrationCom.customerScorecardDiscountDetail.discountCategory'
Most code cut out for simplicity. I know the data is there, cause if i just use {!DiscountDetails} in visualforcepage, the data comes out for the whole class,var names and everything. Just looking to get particular vars.
public class MyController{
private apiMyIntegrationCom.customerScorecardResponse custScoreCard;
......
public apiMyIntegrationCom.customerScorecardDiscountDetail[] getDiscountDetails(){
return this.custScoreCard.discountDetails;
}
}
VisualForce Page:
<apex:page standardController="Account" extensions="MyController">
<table id="discountTable">
<apex:repeat id="dd" value="{!DiscountDetails}" var="dds">
<tr>
<td>{!dds.discountCategory}</td>
</tr>
</apex:repeat>
</table>
I think you need to add getDiscountCategory() to your apiMyIntegrationCom.customerScorecardDiscountDetail class (and any other fields you wish to expose on VF)
VF needs either explicit getProperty(), setProperty() methods or this notation: public String property {get; private set;}. Some more info can be found in my other answer: https://salesforce.stackexchange.com/a/9171/799
It looks like your class is autogenerated from WSDL file? Yep, that means you need to modify this code by sprinkling getters everywhere and you'll have to repeat this process every time you regenerate the class...

Not able to show related records

I have two custom objects, X and Y.
The object Y is related to X by lookup YretatedX__c.
I am trying to show all Y related to X y standart page of X whith a visualforce.
Visualforce:
<apex:page standardController="X__c" extensions="related_list">
<apex:detail relatedList="true">
<apex:relatedList list="Y__c" subject="{!AllRelated}"/>
</apex:detail>
</apex:page>
Apex Class:
public class related_list {
private X__c x;
private Id idX;
public List<Y__c> AllRelated = new Y__c[]{};
public related_list(ApexPages.StandardController controller) {
this.x=(X__c)controller.getRecord();
idX = this.x.Id;
}
public List<Y__c> getAllRelated() {
AllRelated = [SELECT id FROM Y__c WHERE YretatedX__c =: this.idX];
return AllRelated;
}
}
In X page, the visualforce only shows:
Invalid parameter value "[a120E0000001234567, a120E0000007654321]" for parameter "id"
This Ids are valid for Y objects retated to this X object
I tried a lot, but I can find a solution.
I think you're not understanding the attributes of the apex:relatedList component in Visualforce.
Refer to this:
https://developer.salesforce.com/docs/atlas.en-us.pages.meta/pages/pages_compref_relatedList.htm
Note that you don't actually need to query for the records to display them with the component.
All you need is this:
<apex:relatedList list="Contacts"/>
You need to specify the Relationship Name for the list attribute
You don't need to specify the subject (the subject is the record who is the Parent of the list you are trying to show) as this would automatically be populated by the Standard Controller
Hope that helps.
I found a solution using <apex:pageBlockTable instead of <apex:relatedList
<apex:page standardController="X__c" extensions="related_list">
<apex:pageblock id="CustomList" title="Y" >
<apex:pageBlockTable value="{!AllRelated}" var="y" rendered="true">
<apex:column value="{!y.id}"/>
</apex:pageBlockTable>
</apex:pageblock>
</apex:page>

Resources