apex:actionFunction rerender on non visualforce components - salesforce

I have an HTML table setup in a visualforce page with some functionality that appears to be outside of the grasp of a standard apex:datatable. When a user updates the information for one of the rows, I'm attempting to rerender the table so the updated values are reflected. If I use an apex:datatable this works fine, BUT then i lose a lot of the functionality I had to add in my table.
The structure is fairly simple, but this is how it goes:
<table>
<thead>
<tr>
<th>Col 1</th>
</tr>
</thead>
<tbody>
<apex:outputPanel id="table-panel">
<apex:repeat value="{!Parent}" var="row">
<tr name="{!row.Id}">
<td>Cell 1</td>
</tr>
<apex:repeat value="Child__r" var="child">
<tr name="child-{!row.Id}">
<td>Child Cell 1</td>
</tr>
</apex:repeat>
</apex:repeat>
</apex:outputPanel>
</tbody>
</table>
This is in essence the functionality I'm trying to accomplish, with a parent object's children listed below it. As of right now, the rerender converts all my table elements into spans and completely garbles everything. Is it possible to rerender a non-visualforce component, or, alternatively, is there a way I could reproduce this functionality in an apex:datatable?
Thanks!

Its easy. Try this, works fine for me even after rerender:
<apex:panelGrid columns="1" width="400" id="myTable">
<apex:facet name="header">
<apex:outputText value="My table header"/>
</apex:facet>
<apex:repeat value="{!Object}" var="row">
<apex:outputText value="{!row.name}" style="display:block;font-weight:bold;"/>
<apex:repeat value="{!row.ObjectChild__r}" var="child">
<apex:outputText value="{!child.name}"/> <br/>
</apex:repeat>
</apex:repeat>
</apex:panelGrid>
Noe you can reRender your "myTable".

I actually ended up discovering the nifty little "layout" attribute of the apex:outputPanel element. Setting this to "block" completely solved all the problems associated with this.

Related

Salesforce Lightning Component

I am creating a salesforce lightning component to list the leads of the current logged in user.
I have managed to write the following code, but when i add the component to the page, and preview it, I dont see any leads.
<aura:component implements="forceCommunity:availableForAllPageTypes" access="global" >
<div class="slds">
<table class="slds-table slds-table--bordered slds-table--striped">
<thead>
<tr>
<th scope="col"><span class="slds-truncate">Company</span></th>
<th scope="col"><span class="slds-truncate">Annual Revenue</span></th>
</tr>
</thead>
<tbody>
<aura:iteration items="{!v.leads}" var="lead">
<tr>
<td>{!lead.Company}</td>
<td>{!lead.AnnualRevenue}</td>
</tr>
</aura:iteration>
</tbody>
</table>
</div>
It will be great, if someone could tell me what is that I am doing wrong. Thank you
You can follow the tutorial for Displaying a Contact List and replace the Logic with that for Leads
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_one_demo_load.htm
This might be because
You have not added a controller on your lightning component.
<aura:component implements="forceCommunity:availableForAllPageTypes" controller="ContactController" access="global" >
You have not declared the attribute "leads" which you have used in the iteration.
<aura:attribute name="leads" type="Lead[]"/>
You have not set the "leads" attribute which you fetched from the Apex controller.
controller.set("v.leads", variableWithLeadsList);
You have not fetched data from the Apex controller. In this case, as mentioned by Rajdeep Dua, https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/events_one_demo_load.htm link explains the whole process and will help you if you replace Contact with Lead.

angularJS - Repeating tr's in a table, but dynamically adding more rows while looping

Since examples always tell more then just words here is what I would like to do in another language
<tr>
<c:forEach items="${items}" var="item">
<td>...</td>
<td>...</td>
<td>...</td>
<c:if test="${item.showWarning}">
</tr><tr><td colspan="3">${item.warning}</td>
</c:if>
</tr>
So this will loop over a set of items and show some properties of these items. If there is a warning, a new row will be added underneath the current row in which the warning will be shown. However, how can I do this in angularJs? If I put a ng-repeat on the tr, it will stop at the first end tag of tr. I have read on some other threads that this is not very easily done, but how can it be done? And yes, I really do want to use a table. Here is my contrived example with angularjs which is obviously not working as I would like it to. Any pointers how this can be done?
JSBin example with tr-ng-repeat
Currently (1.0.7/1.1.5) you can't output data outside the ng-repeat, but version 1.2(see youtube video AngularJS 1.2 and Beyond at 17:30) will bring the following syntax(adapted to your example):
<tr ng-repeat-start="item in items">
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr ng-repeat-end ng-show="item.showWarning">
<td colspan="3">{{item.warning}}</td>
</tr>
The idea is that whatever is between -start and -end will be repeated including the -end element.
One solution that I can think of is having multiple tbody tags within the same table. Here is a discussion on the use of multiple tbody tags within the same table.
So, for your issue, you could have the following setup:
<table ng-controller="ItemController">
<thead>
<th>Name</th>
<th>Description</th>
<th>warning?</th>
</thead>
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3" style="text-align: center">Warning !!!</td>
</tr>
</tbody>
</table>
Repeat the table body as many times as there are entries for the table and within it have two rows - one to actually display the row entry and one to be displayed conditionally.
You can repeat over the tbody
<tbody ng-repeat="item in items">
<tr>
<td>{{item.name}}</td>
<td>{{item.description}}</td>
<td>{{item.warning}}</td>
</tr>
<tr ng-show="item.warning">
<td colspan="3">Warning !!!</td>
</tr>
</tbody>
Also you do not need to wrap the ng-show expression in {{}}, you can just use item.warning

How can we use a condition statement in email template?

I have one issue related to visualforce email template please help me out.
I am using below code to hide the tr:
<apex:repeat var="cx" value="{!relatedTo.Airline_Conf_s__r}">
<tr style="{!IF(!cx.Include_in_Confirmation__c == true,"display:none!important; ","")}">
<td>
<apex:outputText value="{!cx.Airlines_Url__c}" escape="false" />
</td>
</tr>
</apex:repeat>
but i need it to done without inline style .how can it possible.
You could try using the "rendered" attribute of apex:outputtext, like this
<apex:outputText rendered = "{cx.Include_in_Confirmation__c}" value="{!cx.Airlines_Url__c}" escape="false" />
You are better off using an apex:outputPanel tag and using the rendered property:
<apex:repeat var="cx" value="{!relatedTo.Airline_Conf_s__r}">
<apex:outputPanel layout="none" rendered="{!cx.Include_in_Confirmation__c == true}">
<tr>
<td>
<apex:outputText value="{!cx.Airlines_Url__c}" escape="false" />
</td>
</tr>
</apex:outputPanel>
Note that the layout attribute is set to "none" this will effectively tell VF not to render a tag but you will get the benefits of being able to dynamically render the TR tag as the repeater loops.

ICEfaces: How to pass parameters from one page to another

I have this simple scenario which doesn't work: I use icefaces and i have a simple page with some inputTexts and a submit button, this button will redirect to another page that will display the values of these inputTexts... my question is how can i get the values of these inputTexts from the request and display them in another page?
When i use the following API in the other page backbean, i get only the name of the page that holds the inputTexts:
FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
I really did spent alot of time trying to get this thing to work, so any help will be appreciated.. THx
my page code is:
<ice:form id="form1">
<table border="0">
<tbody>
<tr>
<td><ice:outputText value="Name"></ice:outputText><br></br></td>
<td><ice:inputText id="name" value="#{newContest.name}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="End Date"></ice:outputText></td>
<td><ice:inputText id="endDate" value="#{newContest.endDate}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="private? (only you can see the entries)"></ice:outputText></td>
<td><ice:inputText id="private" value="#{newContest.isPublic}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="Price"></ice:outputText></td>
<td><ice:inputText id="price" value="#{newContest.price}"></ice:inputText></td>
</tr>
<tr>
<td><ice:outputText value="Description"></ice:outputText></td>
<td><ice:inputTextarea id="description" value="#{newContest.description}"></ice:inputTextarea></td>
</tr>
<tr>
<td><br></br><ice:commandButton value="proceed to payment" style="color:blue" action="#{newContest.createContest}"></ice:commandButton></td>
</tr>
</tbody>
</table>
You can bind another bean with current one as a managed property in faces-config.xml as follows.
<managed-bean>
<managed-bean-name>newContest</managed-bean-name>
<managed-bean-class>com.newContest</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>anotherBackingBean</property-name>
<property-class>com.AnotherBackingBean</property-class>
<value>#{anotherBackingBean}</value>
</managed-property>
</managed-bean>
<navigation-rule>
<navigation-case>
<from-outcome>view-anotherBackingBean</from-outcome>
<to-view-id>/jsp/another-page.jspx</to-view-id>
</navigation-case>
</navigation-rule>
Bean Content
Class NewContest {
public AnotherBackingBean anotherBackingBean;
//-- set/get & other methods
public String redirectToAnotherBackingBean(){
anotherBackingBean.setSomeObject(object);
//-- set custom fields
return "view-anotherBackingBean";
}
}
Then you can get your fields directly available in other bean which have been set in current bean.

Salesforce (VisualForce): How to test for no records returned in 'apex:repeat' statement?

I am trying to figure out how to test fields (included within a apex:repeat) to see if they are blank, or null, and if so display some alternate text (Ex: No records to display) in the table instead of a blank table. Existing code snippet below:
<apex:repeat var="auditList" value="{!relatedTo.Site_Audit__r}">
<tr>
<td>
<apex:outputField value="{!auditList.Audit_Type__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Delivery_Date__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Review_Date__c}" />
</td>
</tr>
</apex:repeat>
So in pseudo code I am looking for a test such as:
IF RELATED RECORDS FOUND FOR APEX:REPEAT PERFORM FOLLOWING:
<apex:repeat var="auditList" value="{!relatedTo.Site_Audit__r}">
<tr>
<td>
<apex:outputField value="{!auditList.Audit_Type__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Delivery_Date__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Review_Date__c}" />
</td>
</tr>
</apex:repeat>
ELSE IF NO RELATED RECORDS PERFORM FOLLOWING:
<tr>
<td>
No records to display.
</td>
</tr>
Thanks in advance for the help!
Update in response to first answer from 'eyescream'
Gave the apex:pageBlock method a shot, but ran into the following error when trying to save/deploy:
Result: FAILED Problem: <messaging:emailTemplate> cannot contain <apex:pageBlock>.
Now this is a email template that produces an attached PDF (see general outline of the code below). So is that the case...pageBlock is not allowed within a email template? Thanks for the help!
<messaging:emailTemplate subject="Your requested quote #{!relatedTo.Name}"
recipientType="Contact"
relatedToType="X360_Contract_Cycle__c">
<messaging:plainTextEmailBody >
.
.
.
</messaging:plainTextEmailBody>
<messaging:attachment renderAs="pdf" filename="{!relatedTo.name}">
.
.
.
<apex:pageBlock rendered="{!AND(NOT(ISNULL(auditList)),auditList.size>0)}">
<apex:repeat var="auditList" value="{!relatedTo.Site_Audit__r}">
<tr>
<td>
<apex:outputField value="{!auditList.Audit_Type__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Delivery_Date__c}" />
</td>
<td>
<apex:outputField value="{!auditList.Review_Date__c}" />
</td>
</tr>
</apex:repeat>
</apex:pageBlock>
<apex:pageBlock rendered="{!OR(ISNULL(auditList),auditList.size=0)}">
<i>No records to display.</i>
</apex:pageBlock>
.
.
.
</messaging:attachment>
</messaging:emailTemplate>
Generally speaking - wrap your code in higher page element (like <apex:pageBlock>) and then use the attribute rendered. It's optional and available on most of the page elements, the component reference should give you complete list of attributes supported for each tag.
In your case I suppose something like that should do the trick:
<apex:pageBlock rendered="{!AND(NOT(ISNULL(auditList)),auditList.size>0)}">
Stuff is in, put "repeat" tag here.
</apex:pageBlock>
<apex:pageBlock rendered="{!OR(ISNULL(auditList),auditList.size=0)}">
No records to display.
</apex:pageBlock>
Feel free to experiment with the syntax. I've used the function names as in the formula editor (for formula fields, validation rules etc.) but normal logic operators like &&, || should be available too.
Use a wrapper ( is my personal favorite), and use a formula that checks the size of the list for the rendered attribute.
<apex:outputPanel rendered="{!relatedTo.Site_Audit__r.size = 0}">
No Records
</apex:outputPanel>
<apex:outputPanel rendered="{!relatedTo.Site_Audit__r.size != 0}">
<apex:repeat var="auditList" value="{!relatedTo.Site_Audit__r}">
...
</apex:repeat>
</apex:outputPanel>
Stick with the wrapper (use apex:outputPanel or apex:variable) and create a method that returns the list size i.e.
public Integer listSize{get {
if(auditList != null)
return auditList.size();
else
return 0;}}
Use this in the conditional that determines visibility.

Resources