How to hide a section of fields using a checkbox? - salesforce

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.

Related

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).

Repeat a form and passing it custom objects

In my VF page I have a form which uses map of a hardcoded custom object for some operations (Schema.Sobjecttype.object1_c.fields.getMap()).
Now I want to repeat this same form three times in the same page each time it takes a different custom object.
<apex:page>
<apex:repeat .... give the 3 custom objects in a loop>
<apex: form>
//form code
</apex:form>
</apex:repeat>
</apex:page>
The form code is done inside a controller. So I want to know if I can give a list of sobjects to loop through and if yes then how?
Why don't you make the form a visualforce component and use the object name as a parameter for the component. Then in the component controller, load the getMap() for that object and show in the component.

error checking at the controller level making fields required

I have a VF page with a lot of fields. the requirement is that all the error messages on the fields need to be listed together at the top of the page and have field level error messages. Currently, we have something like this:
<apex:inputField value = 'f1' />
<apex:inputField value = 'f2' />
When the user clicks submit, at the controller level, I check if either of the fields are blank, and if they are, i return an aggregated error. but i don't know how to render the red required bar since all this is happening at the controller level
Basically, the requirement is
for the required fields have a red bar
if the fields are not filled in, display field level errors
For all the field level errors, display a message at the top of the page saying the user needs to enter in these values
You can use (Required="true") attribute. This attribute is of apex:inputField tag. This attribute will give you field level error. you dont need to do coding in controller.
And for all field level errors, you have to add one VF tag <apex:pagemessages />. this tag will show you all error messages together.
If you want to take it a step further and add errors for business logic rather than just empty fields, take a look at the addError() functionality within APEX code.
http://wiki.developerforce.com/page/An_Introduction_to_Exception_Handling

Visualforce passing static resource URL to Apex

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.

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