function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SeanMSSeanMS 

How to Pass an Integer Parameter to a Controller Extension Function?

Hello,

 

I need some guidance on how to pass an integer parameter from a VisualForce Page into a controller extension function (or constructor?). Thank you for any help you can provide as I feel SO close! :)

 

Here's the VisualForce Code:

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

<apex:page standardController="Order_Details__c" extensions="OrderItemController">

      <apex:pageBlock>

          <table border="0" width="100%">

          <apex:repeat var="cx" value="{!Order_Details__c.Shipping_Locations2__r}">

              <tr><td><b>Ship To:</b></td></tr>

              <tr><td><b>{!cx.Last_Name__c}, {!cx.First_Name__c} ({!cx.Address_Type__c})</b></td></tr>

              <tr><td>{!cx.Street__c}</td></tr>

              <tr><td>{!cx.City__c}, {!cx.State_Province__c} {!cx.Postal_Code__c}</td></tr>

              <tr><td>Phone: {!cx.Phone__c}</td></tr>

              <tr><td>Email: {!cx.Email__c}</td></tr>

              <tr><td>&nbsp;</td></tr>

             

              <tr><td>

             <!-- Next line/area is where I need to pass the current value of {!cx.Shipping_Location_Id__c} to either the getOrderItemList function or set it in another function. How do I do this? -->

                  <apex:pageBlockTable value="{!OrderItemList}" var="item">

                     <apex:column  value="{!item.SKU__c}"/>

                     <apex:column value="{!item.Name__c}"/>

                     <apex:column value="{!item.Quantity__c}"/>

                     <apex:column value="{!item.Weight__c}"/>

                     <apex:column value="{!item.Supplier__c}"/>

                     <apex:column value="{!item.Dropship__c}"/>

                     <apex:column value="{!item.Status__c}"/>

                     <apex:column value="{!item.Price__c}"/>

                     <apex:column value="{!item.Ext_Price__c}"/>

                  </apex:pageBlockTable>

              </td></tr>

             

              <tr><td>&nbsp;</td><td></td><td></td></tr>

          </apex:repeat>

          </table>

      </apex:pageBlock>

</apex:page>

 

 

Here's the Controller Function:

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

public class OrderItemController {

 

    public OrderItemController(ApexPages.StandardController controller) { }

   

    public Order_Item__c[] getOrderItemList()

    {

          return [select Order_Item_ID__c, Shipping_Location_Id__c, SKU__c, Image_Path__c,

              Name__c, Quantity__c, Weight__c, Supplier__c, Dropship__c, Shipping_Location_Name__c,

Status__c, Price__c, Ext_Price__c from Order_Item__c where Shipping_Location_Id__c = 5395]; // ß- this needs to come from a variable/parameter that is passed from the VF Page

    }

}

 

 

jdl2009jdl2009

I am not sure if I fully understood your issue.

How do you get to that page? Can't you just pass an URL parameter and the read the parameter from the controller?

SeanMSSeanMS

I just need to know how to pass an *Integer* parameter from my VisualForce page to my Controller. Since my last post, I've tried using the apex:param tag along with getter/setter methods in the controller, but my variable is not getting set! Here's what I have now. Any ideas?

 

 

public class OrderItemController { public OrderItemController(ApexPages.StandardController controller) { } public Integer shipLocId; public void setShipLocId(Integer n) { shipLocId = n; } public Integer getShipLocId() { return shipLocId; } public Order_Item__c[] getOrderItemList() { return [select Order_Item_ID__c, Shipping_Location_Id__c, SKU__c, Image_Path__c, Name__c, Quantity__c, Weight__c, Supplier__c, Dropship__c, Shipping_Location_Name__c, Status__c, Price__c, Ext_Price__c, Mods__c, Design__c, Text1__c, Wear_Date__c from Order_Item__c where Shipping_Location_Id__c = :this.shipLocId]; } }

 

 

<apex:page standardController="Order_Details__c" extensions="OrderItemController">
<apex:stylesheet value="{!$Resource.E6MasterStyles}"/>
<apex:pageBlock>
<table border="0" width="100%">
<apex:repeat var="cx" value="{!Order_Details__c.Shipping_Locations2__r}">
<tr><td colspan="3"><b>Ship To:</b></td></tr>
<tr><td><b>{!cx.Last_Name__c}, {!cx.First_Name__c} ({!cx.Address_Type__c})</b></td>

... more cx variables here ...

<tr><td colspan="3" class="smallText">
<apex:param name="shipLocId" value="{!cx.Shipping_Location_Id__c}" assignTo="{!shipLocId}"/>
<apex:pageBlockTable value="{!OrderItemList}" var="item">
<apex:column value="{!item.SKU__c}"/>
<apex:column value="{!item.Name__c}"/>
<apex:column value="{!item.Quantity__c}"/>
<apex:column value="{!item.Weight__c}"/>
<apex:column value="{!item.Supplier__c}"/>
<apex:column value="{!item.Dropship__c}"/>
<apex:column value="{!item.Status__c}"/>
<apex:column value="{!item.Price__c}"/>
<apex:column value="{!item.Ext_Price__c}"/>
</apex:pageBlockTable>
</td></tr>

<tr><td>&nbsp;</td><td></td><td></td></tr>
</apex:repeat>
</table>
</apex:pageBlock>

</apex:page>

 

 

 

 

 

 

 

jdl2009jdl2009

So you want to call getOrderItemList within the repeat jsut to show Order_Item__c associated with a shipping location... can you do that?

Why don't you just query all the Order_Item__c and render the columns when the shipping location ids match (cx and item)?

SeanMSSeanMS

Yes, I need to cal getOrderItemList within the repeat tag because each Shipping_Location object being looped through by the repeat tag can have multiple Item objects associated to it. This code works if I *hardcode* a particular Shipping_Location Id into the SELECT statement in the controller, so why wouldn't a variable value work in place of that hardcoded value? This really should be something simple, so it's very frustrating! I must be doing something silly.

 

This post describes the overall task...

http://community.salesforce.com/sforce/board/message?board.id=Visualforce&thread.id=18009

 

 

SeanMSSeanMS

Oh - just reread your last post - I don't think it would a good idea to query all of the Order_Item__c objects since eventually there could be MANY.

 

Can someone please take a look at my last code and clue me into some ideas as to why my controller variable is not being set?

 

Thanks so much!

ThomasTTThomasTT

You are really close to the solution, but you need to re-consider the flow. Usually, we do that inthe following steps:
1. User or initial page rendering makes an action
2. A markup like actionSupport, commandButton send a value ( your integer ) as apex:param and call action method (in your case, you don't need to call) and re-render component (your table)
3. Controller prepares data for the component (list of the record) with using assigned value(your integer)
4. The component is rendered with a new data
so, to pass the integer, you need an action. It depends on how the integer is set on the page. If user sets it, then clicking on a button would be the acton. Or onChange with actonSupport.

And if the integer is entered by user, I'm sure thatn you can get the integer from the controller via the inputText/Field.

That's the reason why other poster asked what you want to do...

ThomasTT

Message Edited by ThomasTT on 10-24-2009 12:22 AM
SeanMSSeanMS

Thanks for the reply, ThomasTT.

 

So, I guess that my main goal is simply to *display* this data. I don't want it to be editable, so I'm not sure which type of action I could use in this case. The Integer is a piece of data that is used to map to other object records (like an external id), but not writeable by the user.

 

ThomasTTThomasTT

Hmm, you seem completely understand the concept, so you'll make it. To help you to make it readonly or even invisibule, you can use apex:inputHidden, which emulates input type="hidden".

I'm still wondering what kind of external id could be "Initially" "on the page"... to me, that situation is almost unreal.

 

I still feel that you are doing something wrong in the first place. Again, how the page gets the integer in the first place?

If that number is static - everytime same number - you just hardcode it to the controller...

If it is dynamic, but it comes from another page, then that integer should be in the URL parameter (e.g. http://...?theNumber=1234) and you can get the number in the controller (ApaxPages.currentPage().getParameters().get('theNumber')) and you keep it in the controller to use it for your query.

If it is supposed to be entered by user, then it needs to be editable, which is not for this case.

That's why, your question seems very very strange and I guess jdl2009 felt it in the same way...

ThomasTT

Message Edited by ThomasTT on 10-26-2009 11:10 AM
SeanMSSeanMS

>> Hmm, you seem completely understand the concept, so you'll make it.

 

I sure hope so! :)

 

>> To help you to make it readonly or even invisibule, you can use apex:inputHidden, which emulates input type="hidden".

 

This might just be the answer I've been looking for! I'll try it.

 

>> I'm still wondering what kind of external id could be "Initially" "on the page"... to me, that situation is almost unreal.

 

Hmmm... I don't think I've explained what I'm doing clearly enough. The external id is not displayed on the page at all. It's just included in the data that I query on the Shipping_Location object (the Shipping_Location's unique id that maps to all associated Item objects). I don't think it's that strange of a thing to do in general programming whereby I have a couple of related objects that are mapped together by an unique id. I just want to display some properties of the parent object (name etc) and also display some properties of the related child objects (there could be 0-many). So, in order to do this, I have to know the parent's unique id so that I can grab all of its related child objects (I'm storing the parent unique id in the child object too).

 

>> I still feel that you are doing something wrong in the first place. Again, how the page gets the integer in the first place?

 

The integer is an unique id stored in a hidden field of my parent object (Shipping_Location). It ultimately comes from my company's software app database since we are doing an integration. It's basically a PK for the database record. It's not much different from a unique Salesforce id (like an autonumber). 

 

>> If that number is static - everytime same number - you just hardcode it to the controller...

 

It's not static. There can be MANY of these records, but each record has its own unique id.

 

>> If it is dynamic, but it comes from another page, then that integer should be in the URL parameter (e.g. http://...?theNumber=1234) and you can get the number in the controller (ApaxPages.currentPage().getParameters().get('theNumber')) and you keep it in the controller to use it for your query.

 

It doesn't come from another page. I'm just trying to simply display data (related child record data) on a tab. But, maybe that getParameters call will help me?

 

>> If it is supposed to be entered by user, then it needs to be editable, which is not for this case.

 

Right, I just want to display read-only data.

 

>> That's why, your question seems very very strange and I guess jdl2009 felt it in the same way...

 

Hmmm... well, I aprreciate your effort to understand and help me. I guess I just don't know what's strange about wanting to display data :) I probably just confused the issue by not explaining it clearly.

 

 

ThomasTTThomasTT

Wait, so you're saying, you get the integer from your query, and you want to use it again to query the child records, that's it!?? If so, it's not about the page! it is only in the controller...

 

Remember, all variables (except ones you defined as transient) are kept in the controller, even ones which are not related to any field on the page. Even after page transitions, if the transitions are between pages which use the same controller AND you don't set setRedirect(true), those values are kept (in View State).

 

As long as the integer is got in the controller and used in the controller, you don't need to do anything. Only when you use redirect or go to different page (which uses different controller), you pass values via URL parameter. In both of the situation, you don't need to do anything on the VF page (markups)...

 

So, your original question was already in a wrong direction...

 

ThomasTT

SeanMSSeanMS

Yes, yes! I basically grab the integer from a query... It is actually stored with the dataset that is defined in my VF Page repeat tag (Order_Details__c.Shipping_Locations2__r) --- you'll see if you look at the last code I posted. So, the variable that I want to pass into the controller (which at this point handles only the Items) is cx.Shipping_Location_Id__c.

 

So, do you think this isn't possible? Passing an Integer parameter to a controller from a VisualForce Page?

 

 

 

 

ThomasTTThomasTT

You don't "pass" the value, the value "stays" in the contoller. If you define the dataset as class variables (in Java, member fields), any method in your controller can access to it anytime, right? And I'm saying, in any transitions in the controller, the values are stored, let's say, in the session.

 

Again,

 

You don't pass values Controller -> VF Page -> Controller. You keep the value in the controller.

 

 

private integer theInteger;

public PageReference doFirst(){
theInteger = 1234;
}

public PageReference doSecond(){
System.debug('The integer:'+theInteger);
return theInteger;
}

 

ThomasTT

 

 

Message Edited by ThomasTT on 10-26-2009 01:29 PM
ThomasTTThomasTT

Ok, I think I understand what you want to do... You want to show a Order_Details__c, which contains multiple Shipping_Locations2__c, which contains multiple Order_Item__c, in 1 action without your's input.

 

You're trying to do it in multiple steps, but I think you need to prepare all data at once. I think it is very difficult or impossible.

The easiest way is to define a warper class and set all data at once.

 

public class Wrapper {
public Shipping_Locations2__c location {get; set;}
public List<Order_Item__c> items {get; set;}
}

public List<Wrapper> getLocations(){
// prepare Wrapper object

return wrapperList;
}

 

 

<apex:repeat var="cx" value="{!locations}">
...
<tr><td><b>{!cx.location.Last_Name__c}, {!cx.location.First_Name__c}({!cx.location.Address_Type__c})</b></td></tr>
...
<apex:pageBlockTable value="{!cx.items}" var="item">
<apex:column value="{!item.SKU__c}"/>
...
</apex:pageBlockTable>
</apex:repeat>
 

 

 

 

SeanMSSeanMS

Hi ThomasTT - yes, this is the overall goal. You're exactly right. I think that I confused the issue a lot even though I was trying to simplify - lol.

 

Here's how it needs to work...

1. Salesforce User clicks a custom "Orders" tab (Orders from an ecommerce website).

2. Salesforce User clicks on an individual "Order" record (this is the Order_Details__c object in my code).

3. The Order_Details__c object is loaded showing various Order data.

4. Each Order_Details__c object can have multiple Shipping_Location__c objects related to it (need to show some Shipping_Location data).

5. Each Shipping_Location__c object can have multiple Order_Item__c objects related to it (need to show some Order_Item data).

 

So, I am going to try your Wrapper class idea now, but can you clarify one thing for me? When the Order Detail page loads, I still need to make sure that the Wrapper class knows that particular Order's unique ID so that when I query the Shipping_Location object that I only pull those related to the current Order. How does this work? How in the Wrapper class code do I query "select [fields] from Shipping_Location__c where Shipping_Location_Order_Mapping_Id__c = [current Order ID]"? How does the controller know the current Order Id?

 

Thanks so much! :)

 

SeanMSSeanMS
Ah, ok. I see that I can use ApexPages.currentPage().getParameters().get('id') to get this info. I'll update you later on whether the Wrapper class resolves my issue. Thanks a ton!
ThomasTTThomasTT

Here you go! That's exactly right. That's how we pass values between pages (who uses differnt controlers).

and I recommend that you put your query in your controller and wrapper contains just values...Object-Oriented concept wise, the Wrapper should have it's own query, but in SFDC, the situation is littele bit different. You want to control the number of queries for governer limit, so you want to control SQL statement in one place. If SFDC execute the query when you don't know, you are not happy for it.

So, query data in the controller, and set the value in the wapper. The Wrapper is, litteraly, just a wapper.You should keep it in that way.

Actually, Wrapper is very powerful method. If you use any SObject on the page, I recommend to define Wrapper class in the first place, especially for tables and repeat. If you need to put a checkbox in each row just for multi-selection, you just add a boolean in the wapper. if you define Wrapper class in the middle of development, you need to change all script which uses the object. If you use wrapper in the first place, changing format (you can format a string in the wapper), adding virtual fields, adding a simple logic to convert a string to boolean (e.g. public boolean isProduct {get{return strFlag.indexOf('PRODUCT') == 0) ;}}) is litteraly 2 min.

THomasTT.

Message Edited by ThomasTT on 10-26-2009 03:01 PM
Message Edited by ThomasTT on 10-26-2009 03:01 PM
Message Edited by ThomasTT on 10-26-2009 03:02 PM
SeanMSSeanMS

Thomas (or anyone who can help),

 

I'm having trouble with a Wrapper class. My code is compiling, but I get the following error when loading the Order page. The debug logs show that one row (which is expected) was loaded from the Shipping_Location object. I also output my ids etc to the log and they look correct. What am I doing wrong? Below is a simplified version of the code...

 

Attempt to de-reference a null object

An unexpected error has occurred. Your development organization has been notified.

 

public class shippingLocationWrapper
{
public Shipping_Location__c location {get; set;}
//public List<Order_Item__c> items {get; set;}

public shippingLocationWrapper(Decimal locId)
{
location = [select Id, Last_Name__c, First_Name__c, Address_Type__c, Gift_Note__c,
Shipping_Company_Name__c, Street__c, Shipping_Method__c, City__c, State_Province__c,
Postal_Code__c, Delivery_Date__c, Phone__c, Email__c, Subtotal__c, Shipping_Location_Id__c
from Shipping_Location__c where Shipping_Location_Id__c = :locId];

//populateItems(locId);
}
}

 

public class shippingLocationController {

public shippingLocationController (ApexPages.StandardController controller) {}

public List<shippingLocationWrapper> getLocations()
{
List<shippingLocationWrapper> shippingLocationObjs;

// Select all Shipping Locations linked to this Order...
Shipping_Location__c[] locations = [select Id, Last_Name__c, First_Name__c, Address_Type__c, Gift_Note__c,
Shipping_Company_Name__c, Street__c, Shipping_Method__c, City__c, State_Province__c,
Postal_Code__c, Delivery_Date__c, Phone__c, Email__c, Subtotal__c, Shipping_Location_Id__c
from Shipping_Location__c where Order_Rel__c = :ApexPages.currentPage().getParameters().get('id')];

// For each Shipping Location, create a shippingLocationWrapper object...
for (Shipping_Location__c loc : locations)
{
shippingLocationWrapper thisLocation = new shippingLocationWrapper(loc.Shipping_Location_Id__c);

// Store the shippingLocationWrapper in the shippingLocationObjs List...
shippingLocationObjs.Add(thisLocation);
}

return shippingLocationObjs;
}
}

 

<apex:page standardController="Order_Details__c" extensions="shippingLocationController"> <apex:stylesheet value="{!$Resource.MasterStyles}"/> <apex:pageBlock > <table width="100%"> <apex:repeat var="loc" value="{!Locations}"> Id = {!loc.location.Id}<BR /> </apex:repeat> </table> </apex:pageBlock> </apex:page>

 

It seems like the Apex is working fine, but when I make the call to getLocations from the VisualForce page, it throws that error.

 

Thanks for any help you can provide.

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

ThomasTTThomasTT
Do not ask "YOUR" debugging to others. It is too obvious. There is only 1 object which can be null in the method. - ThomasTT
SeanMSSeanMS
Thomas, I am very new to Apex/VisualForce and unfamiliar with the syntax etc. I learned from another post that I took this to how to check the debug logs and found the issue. I wouldn't ask others to debug for me intentionally or out of laziness, so I'd appreciate if you didn't jump to that conclusion.
Message Edited by SeanMS on 10-29-2009 07:50 AM
ThomasTTThomasTT

We can not keep doing step by step... it will take forever. I know you post another question and Shikibu suggested you to see the log. And the log is supposed to show you which line thorws the exception and you should know which object was null. You didn't even tell me which "line" was the cause in this thread.

 And you didn't reply to Shikibu.

 

I think it is not so polite to drag other people in this way too long.

 

I think the problem is

 

List<shippingLocationWrapper> shippingLocationObjs = new List<shippingLocationWrapper>();

 

you didn't instantiate the list.

 

The log indicated 

 

            shippingLocationObjs.Add(thisLocation);

 

this line, didn't it?

 

And nobody can keep answering this type of questions until you complete your code. Everybody expects that, at least, the person who post a question understands basic Apex and how to read a log (otherwise, I would suggest to read manual first...). And with looking your original post, I thought you were.


ThomasTT

Message Edited by ThomasTT on 10-29-2009 02:29 PM