Visualforce passing static resource URL to Apex - salesforce

I am trying to pass a static resource URL, via the apex:param tag. The code I have so far is:
VisualForce:
<apex:selectList value="{!SelectedFamily}" onchange="renderGallery();" size="1" label="Product Family">
<apex:actionFunction name="renderGallery" rerender="gallery" oncomplete="renderScripts();">
<apex:param value="{!URLFOR($Resource.NoImage)}" assignTo="{!noImage}"/>
<apex:param value="{!URLFOR($Resource.NoImageThumb)}" assignTo="{!noImageThumb}"/>
</apex:actionFunction>
<apex:actionFunction name="renderScripts" rerender="scriptPanel">
</apex:actionFunction>
<apex:selectOptions value="{!Family}" />
</apex:selectList>
Controller:
public string noImage{ get; set; };
public string noImageThumb { get; set; }
My understanding of apex:param was that I would now be able to call the controller variables after the re-render had occurred and they would be populated with the static resource URL. But unfortunately I keep getting null.
Anyone have any idea why it isn't working?

It works if you provide names for your params --- Visualforce won't process params in this context unless they're named.
<apex:actionFunction name="renderGallery" rerender="gallery" oncomplete="renderScripts();">
<apex:param name="noImg" value="{!URLFOR($Resource.NoImage)}" assignTo="{!noImage}"/>
<apex:param name="noImgUrl" value="{!URLFOR($Resource.NoImageThumb)}" assignTo="{!noImageThumb}"/>
</apex:actionFunction>
If this doesn't work for you right away, please post the rest of your Visualforce code so that we can see where "gallery" and "scriptPanel" are in relation to your apex form tag --- getting rerender to work correctly is notoriously tricky, and entirely dependent on the hierarchical position of the DOM elements getting rerendered. To guarantee that gallery and scriptPanel successfully rerender, put them in separate outputPanels outside the apex form tag, like this:
<apex:outputPanel id="scriptPanel">
Selected Family: {!SelectedFamily}<br/>
</apex:outputPanel><br/><br/>
<apex:outputPanel id="gallery">
No Image: {!noImage}<br/>
No Image Thumb: {!noImageThumb}<br/>
</apex:outputPanel><br/><br/>
#MatthewKeefe, there's absolutely no reason why {!URLFOR()} can't be used as an extension variable --- it compiles to text (e.g. '/resource/123718923'), so Jim's solution here is actually pretty interesting, as it saves him from having to do a SOQL query on the StaticResource object in his controller.

{!URLFOR($Resource.NoImage)} is not meant to be used as a controller/extension variable. It is a direct reference to the static resource (no controller/extension required).
I would recommend you use output panels with a rendered property bound to an Apex variable that is controlled by the action function. That way you could show or hide each version of the image by showing or hiding the output panel.
Alternatively, you may want to look into using JavaScript Remoting for something like this.

Related

Pass one of the list field value to pagename attribute for a apex:include tag

I have a picklist in my custom object. I am creating a visualforce page where different templates need to be embedded. In main VF page, I am iterating this custom object list, where in I have to pass picklist value to this apex:include's attribute "pagename". And I have visualforce pages whose name is same as this pick list value.
Below is the sample codes that I have tried so far but had no luck :
Code 1 --
<apex:page renderAs="pdf" controller="MyCheckLayoutController">
<apex:repeat value="{!listwrapper}" var="cl" >
<apex:include pageName="{!cl.check_layout_type}" > // cl.check_layout_type is variable in wrapper class and it is the name of visualforce page as well.
/* This gives error as variable not found. */
</apex:include>
</apex:repeat>
</apex:page>
Code 2 --
<apex:page renderAs="pdf" controller="MyCheckLayoutController">
<apex:repeat value="{!listwrapper}" var="cl" >
<apex:variable var="type" value="{!cl.check_layout_type}" />
{!type} // This variable contains value
<apex:include pageName="{!type}" >
/* But It doesnot read it's value here. It says pagename cannot be null*/
</apex:include>
</apex:repeat>
</apex:page>
I have tried many ways till now. It would be really great help if some one could answer.
Thanks.
So I actually gave this a try and it looks like the page name needs to be defined in the VF page or must be bound to a getter that return a page ref or a property that has get attribute that returns a page ref. It looks like it cannot be bound to the variable in a repeater. Maybe you should try to see if Dynamic Components might do the trick

Apex:repeat two time

I have a visualforce page with the standardController to a custom object.
I want to get all orders (Orders__c) from an event (Event__c). I started by the offer (Offer__c)
Offer is in master-detail with the event and the event is in master-detail with the orders.
I have tried two following codes:
<apex:page standardController="Caterer_Offer__c" sidebar="false" showHeader="false" >
<apex:repeat var="events" value="{!Caterer_Offer__c.Event__r}">
{!events.Name}
<apex:repeat var="orders" value="{!events.Orders__r}">
<!-- {!orders.Name}-->
</apex:repeat>
</apex:repeat>
At this the error-message in the developer console is:
"Aggregate Relationship is used in an unsupported complex expression containing 'Event__r.orders__r'"
And...then I have trief to save the event and use a new variable to "repeat" all orders. I get no error message, but a error in Salesforce
<apex:page standardController="Caterer_Offer__c" sidebar="false" showHeader="false" >
<apex:repeat var="events" value="{!Caterer_Offer__c.Event__r}">
{!events.Name}
<apex:variable var="e" value="{!events}"/>
<apex:repeat var="orders" value="{!e.Orders__r}">
<!-- {!orders.Name}-->
</apex:repeat>
</apex:repeat>
Error-message: SObject row was retrieved via SOQL without querying the
requested field: Event__c.Orders__r
I cannot explain it and work on it since a few hours....
A standardcontroller's record will only contain the fields referenced in the visualforce page you're using it on. You may need to use a custom controller and extend features of standard controller in these cases. The standard controller addFields() method allows you to extend this to the fields you need in your apex code.
I could find a similar solution here.
I'm not sure from your question which object is the Parent record and which is the child, but my answer is going to be based on Caterer_Offer__c being the parent of Event__c and Event__c being the parent of Order__c, so that you can loop through all Orders for an Event for a Catered Offer which is what I think you want to do.
In short what you are trying to do cannot be done in the way you are trying it is because you are in essence trying to perform a child aggregate query that is two levels deep. In essence you are trying to do:
[SELECT Name, (SELECT Name, (SELECT Name FROM Orders__r) FROM Events__r) FROM Caterer_Offer__c];
However salesforce only allows aggregate child queries one level deep, not more. So you have to add an extension that would have code to probably lazy-load the Orders on an event of some sort with a partial page re-render on a link click or button click. In that case you would make the Visualforce page for the Caterer_Offer__c and child Events__c, then load the child Orders from some user action that calls the extension with a element using the id of the selected Event.
But for the error you specifically asked about it would have been:
<apex:page standardController="Caterer_Offer__c" sidebar="false" showHeader="false" >
<apex:repeat var="event" value="{!Caterer_Offer__c.Events__r}">
{!event.Name}
<apex:repeat var="order" value="{!event.Orders__r}">
{!order.Name}
</apex:repeat>
</apex:repeat>
</apex:page>
But again that's not possible because of the aforementioned single depth child aggregation query limitation in salesforce

apex:inputField Binding Value not updated

I am working with Apex controller and Visual Force page.
Inside of the vf page I had a data table and each row of that table binds to a value from a list that generated from the controller
example code:
<apex:dataTable value="{!List}" var="item" styleClass="class1" >
...
<apex:column headerValue="Header1">
<apex:outputpanel rendered="{!NOT((a=='true'))}">
<div class='estimate-name-column'>
<apex:inputField value="{!item.Name}" required='true' rendered="{!(a=='false')}"/>
</div>
</apex:outputpanel>
</apex:column>
...
</apex:datatable>
As you can see, I was trying to hide some inputFields base on some conditions.
However, there was a problem. If I do the above, those inputFields who get rendered were not binded correctly. After submited the form with this data table, inside my controller all the records' in list Name are null. Even though I saw the 'Name' was posted in http request.
I am guessing is render interfere with the binding? because if I remove the rerendered conditions and display all InputField I can get the values inside the controller after submitting form
any ideas what happened?
If I recall correctly an apex tag must be present on the page in order to be rerendered.
In other words - something (maybe as simple as <span id="long:generated:salesforce:id"></span>) must be in HTML in order for later AJAX updates to inject new content into the placeholder. If it's not rendered, it will stay not rendered.(1)
Instead of rendered try to move your condition to styleor styleclass attributes. Something like
<apex:inputField value="{!item.Name}"
required="{!a=='false'}"
style="display:{!IF(a=='false','inline', 'none')}"/>
visibility:hidden (if you want them to occupy their space but not be seen) or display:none (to have them appear to be completely not there. See also What is the difference between visibility:hidden and display:none?
Footnote:
(1) unless of course you'll rerender a tag that contains "this" tag (something higher in the XML).

How to hide a section of fields using a checkbox?

How to hide a section of fields using a checkbox in visualforce pages?
Assuming the Salesforce approach (keeping the page weight down etc.), you could do something like the following:
<apex:inputCheckbox value="{!theBool}">
<apex:actionSupport event="onChange" action="{!myAction}" rerender="theFieldsPanel"/>
</apex>
<apex:outputPanel id="theFieldsPanel">
<apex:variable var="v" value="" rendered="{!theBool}">
<apex:inputField value="{!someField"} rendered/>
<!-- more fields etc. -->
</apex:variable>
</apex:outputPanel>
Note that I don't use the rendered attribute on the output panel itself, this is because if it's not rendered then it doesn't exist in the page, and as such, doesn't make for a good rerender target! Now you just require a simple action on the controller (you could do any other logic in here if need be):
public Pagereference myAction()
{
// any logic etc. goes here
return null;
}
The benefit of doing things this way, as opposed to with javascript is that you can ensure that if the fields are hidden then values won't be sent back to the controller for the variables they're bound to. Simply hiding things with javascript would not have the same effect, so say the user typed something in one of the fields and then hid them, whatever he/she typed would still end up in the related controller variables.

salesforce cast from sObject to custom object

I have written a Base controller that I want to use to manage data pagination on sever controllers.
I have an abstract method like so
public abstract List<sObject> getPagedData();
Then each of my controllers that extend the base controller implement their own version of getPagedData. But return a specific customer object e.g Foo__c
Can I Cast from List<sObject> to List<Foo__c> in a visualforce page
My page looks like this
<apex:dataTable value="{!PagedData}" var="c" >
<apex:column >
<apex:facet name="header">Foo</apex:facet>
<apex:outputText value="{!c.Bar__r.SomeValue__c]}" />
</apex:column>
But I get an error that sObject does not have know about Bar__r I have tried doing a Cast with the dataTable value and inside the outputText but it does not seem to work
I can use dyamic bindings http://www.salesforce.com/us/developer/docs/pages/Content/pages_dynamic_vf.htm but then how do i do things like
<apex:outputText value="{0, number, $###,###}">
<apex:param value="{!c.Amount__c}" />
</apex:outputText>
<apex:outputText value="{0,date,dd/MM/yyyy}">
<apex:param value="{!c.Date_Of_Birth__c}" />
</apex:outputText>
As i get errors as saying it expects a DateTime object etc
Been there. Unfortunately, there isn't a way to cast objects directly in the visualforce page.
The way I've addressed this is to move all the pagination logic into your base controller in generic form and then have the child controllers take on the responsibility for casting the data into the form your visualforce page expects.
public List<Foo__c> getFooPagedData() {
List<Foo__c> fooPagedData = new List<Foo__c>();
for(SObject record : getPagedData()) {
fooPagedData.add((Foo__c) record));
}
return fooPageData;
}
You might also consider using the StandardSetController to control your pagination. It works great for custom objects and most standard objects, but not for custom ApexClasses and some standard objects. That said you'll still need to cast your result set as it to returns a List from its getRecords() method.

Resources