Below is the code snippet:
tansaction.xhtml
<h:form id="form1">
<p:dataTable value="#{transactionMB.transactionEntryList}" var="transInfo" rowStyleClass="tdDownValue">
</p:dataTable>
</h:form>
<h:form id="form2">
<p:dataTable value="#{transactionMB.loggingList}" var="logInfo" rowStyleClass="tdDownValue">
</p:dataTable>
</h:form>
<h:form id="form3">
<p:dataTable value="#{transactionMB.salesEntryList}" var="salesInfo" rowStyleClass="tdDownValue">
</p:dataTable>
</h:form>
Please suggest.Thanks in advance.
The idea is to start long-running initialization of lists after the page load.
You can try something like:
Do not initialize your lists in bean constructor/post construct method. Instead of it, add to the bean public methods, that you will call after page load.
public void loadTransactionEntryList();
public void loadloggingList();
public void loadSalesEntryList();
Add loading indicators near the table, and remoteCommands to call load* methods. Note, that by default loading indicators are shown and tables are hidden. oncomplete call is used to toggle indicator and table after command finishes.
<h:form id="commands-form">
<p:remoteCommand name="loadTransactionEntryListCommand" action="#{transactionMB.loadTransactionEntryList}"
update=":form1" oncomplete="hideLoadingDisplayTable('#form1');"/>
<p:remoteCommand name="loadloggingListCommand" action="#{transactionMB.loadloggingList}"
update=":form2" oncomplete="hideLoadingDisplayTable('#form2');"/>
<p:remoteCommand name="loadSalesEntryListCommand" action="#{transactionMB.loadSalesEntryList}"
update=":form3" oncomplete="hideLoadingDisplayTable('#form3');"/>
</h:form>
<h:form id="form1">
<div class="loading-indicator" style="display: block;">...</div>
<p:dataTable value="#{transactionMB.transactionEntryList}" var="transInfo" rowStyleClass="tdDownValue" style="display: none;">
</p:dataTable>
</h:form>
<h:form id="form2">
<div class="loading-indicator" style="display: block;">...</div>
<p:dataTable value="#{transactionMB.loggingList}" var="logInfo" rowStyleClass="tdDownValue" style="display: none;">
</p:dataTable>
</h:form>
<h:form id="form3">
<div class="loading-indicator" style="display: block;">...</div>
<p:dataTable value="#{transactionMB.salesEntryList}" var="salesInfo" rowStyleClass="tdDownValue" style="display: none;">
</p:dataTable>
</h:form>
Call commands with JavaScript in the end of the document or with jquery's (document ).ready().
<script type="text/javascript">
loadTransactionEntryListCommand();
loadloggingListCommand();
loadSalesEntryListCommand();
</script>
Finally, implement hideLoadingDisplayTable(formId) function to hide loading indicator and show table with JavaScript.
Why don't you use pagination with lazy loading in your data tables. Only first page of data will be loaded when your XHTML page is loaded, which should certainly reduce your load time.
Extend LazyDataModel and implement load(...) methods to lazy load your data in tables.
Initiate your database connections, and create your custom lazyDataModel objects in a method of your backing bean which is annotated with #postConstruct. Maintain current page and page size in your lazyDatalModel. In load(...) method get the next page from the database and return.
These are few links to help you.
Primefaces datatable paginationand lazy loading, see primefaces showcase -
http://www.primefaces.org/showcase/ui/data/datatable/lazy.xhtml
JDBC pagination -
http://java.avdiel.com/Tutorials/JDBCPaging.html
If you are using Persistance (JPA or Hibernate ), see for setFirstResult() and setMaxResult() methods of Query object.
Related
i have a simple contact form with an underlying transient view.
<f:view transient="true">
<h:panelGroup id="messages" layout="block" >
<o:messages escape="false" infoClass="info" errorClass="error" globalOnly="true" rendered="#{not empty facesContext.messageList}" />
</h:panelGroup>
<h:form id="contactform">
please enter your name:
<h:inputText id="name" required="true" requiredMessage="#{msg.fieldrequired}">
...
</h:form>
</f:view>
this page is also cached (using omnifaces CacheControlFilter), since the content here is not really dynamic and the user only submits some request parameters. when the form has been submitted sucessfully, the managedbean adds a flash message and performs a refresh:
public void showSuccess() throws IOException {
Messages.addFlashGlobalInfo("submit_success");
Faces.refresh(); //ensure cleaning all input fields in the form
}
after that, the page now contains the div with the rendered faces message and this message is now present every time the user performs a GET to this page again.
<div id="messages">
<ul>
<li>Thank you for your feedback</li>
</ul>
</div>
is there a way to get rid of the message?
thanks in advance.
I am trying to put a p:commandButton inside a overlayPanel, to submit the information of a h:form and redirect to another view. So, I use the property action of the button to perform this operation. I have a managed bean associated with this view but the function used for this purpose is never reached. Can u help me?
Here is the code:
advancedSearch-form.xhtml
<h:form>
<h:panelGrid width="100%">
<h:column>
....
</h:column>
....
<p:commandButton value="Submit" action="#{searchForm.save}">
</p:commandButton>
</h:panelGrid>
In another xhtml:
<h:form>
<div>
...
<div class="menu-search">
<p:commandButton id="advancedSearch" icon="ui-icon-carat-1-s" styleClass="ui-search-button" type="button"/>
<p:overlayPanel id="advancedSearchPanel" styleClass="ui-advanced-search-overlay" for="advancedSearch" hideEffect="fade" my="right top" dynamic="true" dismissable="false">
<ui:include src="/search/advancedSearch-form.xhtml"/>
</p:overlayPanel>
</div>
...
</div>
After looking over the properties of overlay, I solved this question by removing the dynamic property of overlaypanel.
I have dashboard with panels:
<p:dashboard id="board" model="#{dashboardOptionsMB.model}">
<c:forEach var="item" items="#{dashboardOptionsMB.emsWidgets}">
<ui:include src="/pages/dashboard/panel.xhtml">
<ui:param name="widget" value="#{item.webDashboardDbBean}" />
<ui:param name="emsValue" value="#{item.emsValue}" />
</ui:include>
</c:forEach>
</p:dashboard>
I load a list dashboardOptionsMB.emsWidgets with content before rendering page, and this works fine with panel component:
panel.xhtml:
<p:panel id="#{widget.widgetid}" header="#{widget.widgetheader}" closable="true" >
<h:outputText value="#{emsValue.value}" />
...
</panel>
So, before each rendering I initialize the list with all elements and content with this method:
DashboardOptionsMB:
private void initWidgets(WebDashboardsDbBean dashboard) {
//dashboard is JPA entity from database
emsWidgets = dashboard.getWidgets();
...
}
What I want to achieve is to load each panel content dynamically after page load. For example each panel should call:
initWidget(String widgetId)
after page load, and when this method is completed to update its content.
Use p:remoteCommand to create some Ajaxified Javascript which will be executed when body is loaded:
<h:body onload="loadWidgets()">
<!-- content -->
<p:remoteCommand name="loadWidgets"
update="#{widget.widgetid}"
actionListener="#{dashboardOptionsMB.initWidgets}"/>
</h:body>
Alternatively, you might use the autoRun="true" argument to have it executed when document is ready:
<p:remoteCommand name="loadWidgets"
update="#{widget.widgetid}"
actionListener="#{dashboardOptionsMB.initWidgets}"
autoRun="true"/>
See also:
JSF lazy loading component value
Make your Primefaces app load faster with lazy loading
Setup:
I have 2 forms A & B
I have a commandLink in form A:
<h:commandLink actionListener="#{homeView.selectDiv('homeUpdates')}">#{msg.homeUpdates}
<f:ajax render=":B" execute="#this" />
</h:commandLink>
...which updates form B.
The problem is that when I click the ajax link, it rebuilds form A as well and gets an exception from a ui:repeat I have. Is this correct behaviour? Should it rebuild form A as well?
I am using JSF 2.2 and form A contains a ui:fragment=>ui:include=>ui:repeat
=====Added SSCCE=======
The following code does not run after pressing Update B! twice. It gives an exception of duplicate id. The value for ui:repeat is irrelevant
<h:head>
</h:head>
<h:body>
<h:form id="A">
<ul class="tableView notification">
<ui:repeat var="notification" value="#{dashboardBean.notifications}">
<li>
xx
</li>
</ui:repeat>
</ul>
<h:commandLink value="Update B!" listener="#{dashboardBean.toggleRendered}">
<f:ajax execute="#this" render=":B" />
</h:commandLink>
</h:form>
<h:form id="B">
</h:form>
</h:body>
Upon initial request the view is created, upon postbacks the view is restored. To recite some points of JSF 2.2 specification for clarity (emphasis mine):
P. 2.2.1:
If the request is not a postback ... call createView() on the ViewHandler. If the request is a postback, ... call ViewHandler.restoreView(), passing the FacesContext instance for the current request and the view identifier, and returning a UIViewRoot for the restored view.
P. 2.5.8:
Selected components in a JSF view can be priocessed (known as partial processing) and selected components can be rendered to the client (known as partial rendering).
P. 13.4:
The JavaServer Faces lifecycle, can be viewed as consisting of an execute phase and a render phase. Partial traversal is the technique that can be used to “visit” one or more components in the view, potentially to have them pass through the “execute” and/or “render” phases of the request processing lifecycle.
When you use AJAX, PartialViewContext class will contain all the information that's needed to traverse the restored view.
So, to get back to your question, under <f:ajax render=":B" execute="#this" /> setup, only the form with id="B" will be rerendered, which implies <h:form id="B">, no form nestings, etc.
Regarding your 'doesn't work' comment the simple test case with a plain view scoped managed bean gave me the expected results:
<h:form id="A" >
<h:outputText value="#{twoFormsBean.a}"/>
<h:commandLink actionListener="#{twoFormsBean.actionA}">
Update B!
<f:ajax execute="#this" render=":B"/>
</h:commandLink>
</h:form>
<h:form id="B" >
<h:outputText value="#{twoFormsBean.b}"/>
<h:commandLink>
Update Both!
<f:ajax execute="#this" render=":A :B"/>
</h:commandLink>
</h:form>
with
#ManagedBean
#ViewScoped
public class TwoFormsBean implements Serializable {
private String a = "A";//getter
private String b = "B";//getter
public void actionA(ActionEvent ae) {
a = "newA";
b = "newB";
}
}
I am creating a simple page that will, after clicking a button, replace one panelGroup with another. First, the code:
<h:body>
<ui:composition template="/elements/templateWithMenu.xhtml">
<ui:define name="content">
<div class="rightContent">
<h:panelGroup id="lol" rendered="#{test.firstStep.booleanValue()}">
<h3>This should disappear</h3>
<h:form id="newPollForm1" rendered="#{test.firstStep.booleanValue()}">
<fieldset>
<h:commandLink value="Next" action="#{test.firstStepCompleted()}" >
<f:ajax execute="#all" render="lol" />
</h:commandLink>
</fieldset>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{test.secondStep.booleanValue()}">
Works!
</h:panelGroup>
</div>
</ui:define>
</ui:composition>
</h:body>
The backing bean simply sets the firstStep as false, and secondStep as true.
Now, when I tried running this, I got <f:ajax> contains an unknown id 'lol' - cannot locate it in the context of the component j_idt39. After googling a bit, I found out that for elements outside the form's scope, I need to use SEPARATOR_CHAR (:). That didn't work. So I tried messing with different combinations of #{component} and #{cc}, but nothing works. I even found this awesome explanation, but again, I failed miserably. If I use #all, everything goes ok (one panel is replaced with another), but I really need to render a specific component.
Help? Please?
You need to update the common parent <div class="rightContent"> instead. This one is always rendered and thus guarantees that JavaScript/Ajax can access and mainpulate its children. Replace it by <h:panelGroup layout="block"> and give it an id.
<h:panelGroup layout="block" id="content" class="rightContent">
<h:panelGroup rendered="#{test.firstStep}">
<h3>This should disappear</h3>
<h:form id="newPollForm1">
<fieldset>
<h:commandLink value="Next" action="#{test.firstStepCompleted()}" >
<f:ajax execute="#form" render=":content" />
</h:commandLink>
</fieldset>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{test.secondStep}">
Works!
</h:panelGroup>
</h:panelGroup>
Using this Test.java class:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class Test {
private int number = 0;
public void firstStepCompleted() {
number++;
}
public boolean isFirstStep() {
return number == 0;
}
public boolean isSecondStep() {
return number == 1;
}
}
Note that I removed the superfluous Boolean#booleanValue() calls and the duplicated rendered contition on the form.
If that still doesn't work, then the /elements/templateWithMenu.xhtml apparently contains another naming container component which has prepended its ID. For starters who haven't memorized all naming container components yet, an easy way to figure the real right client ID is to open the page in browser, rightclick and View Source and then locate the JSF-generated HTML element and take exactly its id attribute value (and prefix it with : in the <f:ajax render>).