Render blocks of page async with JSF + RichFaces - ajax

I want to render 6 blocks on a page asynchronously using richfaces a4j support.
To accomplish this I have defined 6 a4j:region components and an a4j:commandLink for manual refreshing of the components.
Here is the relevant code:
<ui:define name="body">
<h:form id="dashboardform">
<div class="table_container" style="width:99%">
<h:panelGrid id="dashboadPanel" columns="3">
<a4j:region id="resourceGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box">
<ui:include src="dashboard_resourceGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
<a4j:region id="profileGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box" >
<ui:include src="dashboad_profileGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
<a4j:region id="reportGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box" >
<ui:include src="dashboard_reportGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
<a4j:region id="installedBaseGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box" >
<ui:include src="dashboard_installedBaseGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
<a4j:region id="simcardGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box">
<ui:include src="dashboard_simcardGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
<a4j:region id="orderOverviewGraphRegion">
<h:panelGroup>
<div class="rounded_box dashboard_box" id="order">
<ui:include src="dashboard_orderOverviewGraph.xhtml"/>
</div>
</h:panelGroup>
</a4j:region>
</h:panelGrid>
<h:panelGrid id="dashboadRefreshPanel" columns="1" width="100%">
<a4j:commandButton value="#{I18n.messages['dashboard.btn.refresh']}"
action="#{dashboardBean.doRefresh}" reRender="resourceGraphRegion, profileGraphRegion, reportGraphRegion, installedBaseGraphRegion, simcardGraphRegion, orderOverviewGraphRegion"
image="/static/images/refresh.png" style="border:0px; margin-right: 20px; padding: 0px; float: right;" />
</h:panelGrid>
</div>
However, when manually triggering the a4j:commandLink the whole page becomes inactive (grays out) and a loading icon appears.
What I would like is the the page opens up very smoothly and that all 6 regions are rendered async so the user gets a smooth experience and doesn't have to wait for all regions to complete
.

To control the loading notification you can use
<a4j:status id="commonstatus" startText="In progress..." stopText="Complete"/>
This allows you to ste the status field of almoust any "link" to use that status control.
tutorial

Related

p:blockui disable ajax

I have a problem, I'm using p:blockUi to block the full body of my page. The problem is that the AJAX events stopped to work, actually they only work once and then never again.
¿Does anybody now how I can fix it?
Here is my code:
<h:form id="formMenu">
<ul class="menu">
<li><p:commandLink action="alta" value="Alta" id="btn_alta"/></li>
<li><p:commandLink value="Tramitación" id="btn_tramitacion"/></li>
<li><p:commandLink value="Bajas" id="btn_baja"/></li>
<li><p:commandLink action="salir" value="Salir" id="btn_salir"/></li>
</ul>
<p:blockUI block=":full_page" trigger="btn_alta,btn_salir,btn_tramitacion,btn_baja">
<h:panelGrid columns="1">
<h:graphicImage value="/resources/img/ajaxloadingbar.gif"
style="horizontal-align:middle; vertical-align: middle;"/>
<h:outputText value="Cargando..." style="white-space: nowrap;"/>
</h:panelGrid>
</p:blockUI>
</h:form>

Redirecting with return statement influences the rendering process in next page

I have a problem with the rendering of a datatable.
In my application I have this navigation bar:
<h:form>
<ul class="nav nav-tabs">
<li class="active" role="presentation">
<h:commandLink value="Veranstaltungen" action="#{eventController.redirect('veranstaltung.xhtml')}"/>
</li>
<li role="presentation">
<h:commandLink value="Beacons" action="#{beaconcontroller.redirect('beacon.xhtml')}"/>
</li>
[...]
</ul>
</h:form>
Redirect (beaconcontroller):
public String redirect(String link) {
beacons = database.getAllBeacons();
return "./" + link;
}
The navigation works perfectly, but when I submit the form beaconData in the beacon.xhtml my datatable won't be rendered.
<h:form id="beaconsTable">
<p:dataTable value="#{beaconcontroller.beacons}" var="b"
tableStyleClass="table table-striped"
emptyMessage="Keine Beacons verfügbar"
style="font-size:14px"
rowIndexVar="rowIndex"
rowStyleClass="#{(rowIndex mod 2) eq 0 ? 'first-row' : 'second-row'}"
>
<p:column style="float:left;border:none;">
<f:facet name="header">
<h:commandLink actionListener="#{beaconcontroller.sortBeacons}">
<f:ajax execute="#this" render="beaconsTable"/>
Beacons
</h:commandLink>
</f:facet>
<h:commandLink>
<f:ajax listener="#{beaconcontroller.fillFields(b)}" execute="#this" render=":beaconData beaconsTable :delete"/>
<h:outputText value="#{beaconcontroller.getCompleteString(b)}" style="#{beaconcontroller.currentBeacon == b ? 'color:#337AB7' : 'color:#555555'}"></h:outputText>
</h:commandLink>
</p:column>
</p:dataTable>
</h:form>
</div>
<div class="col-lg-6">
<h:form role="form" id="beaconData" enctype="multipart/form-data">
<div class="form-group">
<label>UUID*</label>
<h:inputText id="id_uuid" binding="#{uuidAttribute}" class="form-control" value="#{beaconcontroller.uuid}" p:placeholder="Unternehmen" required="true" requiredMessage="Bitte UUID angeben" validatorMessage="Bitte nur Zahlen und Buchstaben angeben">
<f:validateRegex pattern="[0-9a-zA-Z]+"/>
</h:inputText>
<h:message styleClass="errMessage" for="id_uuid" style="color: red"/>
</div>
[...]
<h:commandButton type="submit" value="Speichern" actionListener="#{beaconcontroller.saveData}" class="btn btn-primary" disabled="#{beaconcontroller.currentBeacon == null}">
<f:ajax render="beaconData :beaconsTable" execute="#form"/>
</h:commandButton>
</h:form>
</div>
Clicking on an other entry in the datatable, solves the problem. Then the table will be rendered on submit. But why dosen't it work on the first time?
When I now change action="#{beaconcontroller.redirect('beacon.xhtml')}" in the navigation bar to action="beacon.xhtml" it works all correct. I thought these expressions are meaning the same?

how i get clicked CommandLink id in Controller in JSF?

<ui:repeat value="#{prodCtr.paginator.model}" var="o">
<h:form>
<h:commandLink id="#{o.id}" action="ModelInfo.xhtml" actionListener="#{prodCtr.listener}">
<h:panelGrid columns="1" style="border: #ffffff">
<img src="resources/images/#{o.id}.jpg" style="width: 100px;height: 100px"/>
<h:outputLabel value="#{o.price} YTL" style="font-size: 12px;font-family: Georgia, Serif;color: #ff3300" />
<h:commandButton value="Sifaris et" class="button"/>
</h:panelGrid>
</h:commandLink>
</h:form>
</ui:repeat>
java.lang.IllegalArgumentException caught during processing of RENDER_RESPONSE 6 : UIComponent-ClientId=, Message=Empty id attribute is not allowed here
How can i CommandLink id dinamically?Is there an other way?
You don't need to specify the id attribute for the child components when using the <ui:repeat/> tag. It automatically does this.
If you do want to be in control of the id attribute, <ui:repeat/> is the wrong one to use for that. The reason is that at point in time that the components are being placed in the UIViewroot (essentially when the page is being constructed for the first time), the <ui:repeat/> component is not active, i.e. it's not being processed. So the var="o" is not available to the runtime and so nothing is available to be used as id.
To be in control of the id, you should be using the <c:forEach/> tag instead. Your code should look like this:
<c:forEach items="#{prodCtr.paginator.model}" var="o">
<h:form>
<h:commandLink id="#{o.id}" action="ModelInfo.xhtml" actionListener="#{prodCtr.listener}">
<h:panelGrid columns="1" style="border: #ffffff">
<img src="resources/images/#{o.id}.jpg" style="width: 100px;height: 100px"/>
<h:outputLabel value="#{o.price} YTL" style="font-size: 12px;font-family: Georgia, Serif;color: #ff3300" />
<h:commandButton value="Sifaris et" class="button"/>
</h:panelGrid>
</h:commandLink>
</h:form>
</c:forEach>

AJAX on an included page through AJAX

I have a page in which through AJAX I include other pages conditionally. On one included page I would like to do another ajax call.
My initial page:
<ui:composition template="../../templates/template.xhtml">
<ui:define name="title">
Pay
</ui:define>
<ui:define name="content">
<h:form>
<div id="loginDiv">
<div class="homeDiv" style="text-align: left;">
<h:form>
<h:outputText value="#{strings.paymentMainSpeech} " />
<ul id="grileList">
<li>#{strings.payThroughSMS}</li>
<li>#{strings.payThroughCard}</li>
<li>#{strings.payThroughPayPal}</li>
</ul>
<h:outputText value="#{strings.bellowYouHavePaymentOptions}" />
</h:form>
</div>
<h:selectOneRadio value="#{payment.option}" immediate="true">
<f:selectItem itemValue="#{strings.payThroughSMS}"
itemLabel="#{strings.payThroughSMS}" />
<f:selectItem itemValue="#{strings.payThroughCard}"
itemLabel="#{strings.payThroughCard}" />
<f:selectItem itemValue="#{strings.payThroughPayPal}"
itemLabel="#{strings.payThroughPayPal}" />
<f:ajax event="change" listener="#{payment.changeListener()}"
render="payment" />
</h:selectOneRadio>
</div>
<h:panelGroup id="payment">
<!-- PayPal -->
<h:panelGroup rendered="#{payment.option == 'PayPal'}">
<ui:include src="../payments/paypal/paypal.xhtml" />
</h:panelGroup>
<!-- CARD -->
<h:panelGroup rendered="#{payment.option == 'Card'}">
<ui:include src="../payments/card/mobilPay.xhtml" />
</h:panelGroup>
</h:panelGroup>
</h:form>
</ui:define>
I select from the radio buttons the pages which I want to include through an ajax listener. That works well.
On one included page (on mobilPay.xhtml)
<ui:composition>
<ui:define name="title">
Pay Card Mobil Pay
</ui:define>
<div id="loginDiv">
<h:panelGroup id="next">
<h:panelGroup rendered="#{not mobilPayInitBean.forward}">
<h:outputText value="#{strings.paymentSpeech} " />
<h:outputText value="#{strings.paymentSpeech} " />
<h:outputText value=" #{strings.paymentSpeech2}" />
<br />
<br />
<h:form>
<h:selectOneMenu value="#{mobilPayInitBean.options}">
<f:selectItem itemValue="five" itemLabel="#{strings.fiveEuro}" />
<f:selectItem itemValue="seven" itemLabel="#{strings.sevenEuro}" />
<f:selectItem itemValue="ten" itemLabel="#{strings.tenEuro}" />
</h:selectOneMenu>
<br />
<br />
<f:ajax render="next">
<h:commandButton value="#{strings.nextStep}"
action="#{mobilPayInitBean.nextStep()}"
rendered="#{not mobilPayInitBean.forward}" />
</f:ajax>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{mobilPayInitBean.forward}">
<div id="loginDiv">
<form name="frmPaymentRedirect" method="post"
action="#{mobilPayInitBean.paymentURL}">
<input type="hidden" name="env_key"
value="#{mobilPayInitBean.paymentURL}" /> <input type="hidden"
name="data" value="#{mobilPayInitBean.paymentURL}" />
<p>
If not reditect in 5 seconds <input type="image"
src="images/12792_mobilpay-96x30.gif" />
</p>
</form>
</div>
<script type="text/javascript" language="javascript">
window.setTimeout(document.frmPaymentRedirect.submit(), 3000);
</script>
</h:panelGroup>
</h:panelGroup>
</div>
I want to select from the select one menu an item and click on the command button and I want the whole selectonemenu and the command button to disaper and the last form (name="frmPaymentRedirect")to appear.
Now the problem:
I include the mobilPay.xhtml page and the whole page with the radiobuttons and the mobilPay.xhtml page appears, BUT when I click on the command button the hole mobilPay.xhtml disappears and so does the selection in the radio button.
Thank you for your time.
It was the nested forms!!!
I used a master template -> child template -> included page.
In the child template a had a form and inside the form I inserted the pages and in the one inserted page I had another set of form.
Thank you for pointing that obvious thing out!!!

After showing / hiding a JSF element with AJAX how to hide the triggering element?

I followed the intructions given by BalusC in [this answer][1]
[1]: JSF and f:ajax for hiding/showing div and it worked. But I want to hide the element when the command button is pressed and the element with the id="incorrectQuestion" is shown. I did it almost like in the example. I have tried a lot of combinations but I couldn't hide the command button.
<h:panelGroup rendered="#{not answerResultBean.showIncorrectQuestions}">
<div id="loginDiv" style="width: 400px; text-align: left;">
<center>
<f:ajax render="incorrectQuestions">
<br />
<h:commandButton value="#{strings.failedQuestions}"
action="#{answerResultBean.setShowIncorrectQuestions(true)}" />
<br />
<br />
</f:ajax>
</center>
</div>
</h:panelGroup>
<h:panelGroup id="incorrectQuestions">
<h:panelGroup rendered="#{answerResultBean.showIncorrectQuestions}">
<div id="loginDiv" style="width: 400px; text-align: left;">
...
Just put the <h:panelGroup> containing the button inside <h:panelGroup id="incorrectQuestions"> as well. This way it will also be updated on ajax request and the rendered condition would cause it to be hidden.
By the way, try to keep your code DRY. You've there quite some code duplication.
<h:panelGroup layout="block" id="loginDiv" style="width: 400px; text-align: left;">
<h:commandButton value="#{strings.failedQuestions}"
action="#{answerResultBean.setShowIncorrectQuestions(true)}"
style="text-align: center; margin: 10px;"
rendered="#{not answerResultBean.showIncorrectQuestions}">
<f:ajax render="loginDiv">
</h:commandButton>
<h:panelGroup rendered="#{answerResultBean.showIncorrectQuestions}">
...
</h:panelGroup>
</h:panelGroup>
Note that a <h:panelGroup layout="block"> generates a <div>. This way there's no need for a <h:panelGroup><div>.

Resources