JSF, refresh periodically a component with ajax? - ajax

I'm working on an application JSF and i want to refresh periodically a component with ajax Like facebook notification zone behaviour.
How can i do that?

Poll is what you need to use
Poll component make ajax calls in a specified interval.
For example Primefaces Poll
<h:form id="form">
<h:outputText id="txt_count" value="#{counterBean.count}" />
<p:poll interval="3" listener="#{counterBean.increment}" update="txt_count" />
</h:form>
Link to showcase Primefaces Ajax Poll
Pure JSF approach would be to use js timer that will invoke periodical document.getElementById('someFormId:idOfButton').click();
or jquery $("#someFormId\\:idOfButton").click();
while the button will look like this
<h:commandButton id="idOfButton">
<f:ajax render="txt_count"></f:ajax>
</h:commandButton>
something like this
setInterval(function(){$("idOfButton").click()},3000);
More about timer JavaScript Timing Events

In RichFaces there is a poll component as well. Here is a nice example they provide
<a4j:region>
<h:form>
<a4j:poll id="poll" interval="1000" enabled="#{userBean.pollEnabled}" reRender="poll,grid"/>
</h:form>
</a4j:region>
<h:form>
<h:panelGrid columns="2" width="80%" id="grid">
<h:panelGrid columns="1">
<h:outputText value="Polling Inactive" rendered="#{not userBean.pollEnabled}" />
<h:outputText value="Polling Active" rendered="#{userBean.pollEnabled}" />
<a4j:commandButton style="width:120px" id="control" value="#{userBean.pollEnabled?'Stop':'Start'} Polling" reRender="poll, grid">
<a4j:actionparam name="polling" value="#{!userBean.pollEnabled}" assignTo="#{userBean.pollEnabled}"/>
</a4j:commandButton>
</h:panelGrid>
<h:outputText id="serverDate" style="font-size:16px" value="Server Date: #{userBean.date}"/>
</h:panelGrid>
</h:form>

Related

jsf ajax request recreates viewscoped bean

I use JSF 2.2 and Primefaces 3.5, and I have a problem with ajax request when I update parent component:
<h:panelGroup id="PAG_CARTELERA" layout="block">
<h:form id="FRM_CARTELERA">
<h:panelGroup rendered="#{!carteleraController.existeCookieCinePref}">
<ui:include src="/paginas/cartelera/cinePreferidoIn.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{carteleraController.existeCookieCinePref}">
<ui:include src="/paginas/cartelera/carteleraOut.xhtml" />
</h:panelGroup>
</h:form>
</h:panelGroup>
In the page carteleraOut.xhtml I have:
<p:calendar id="CART_FECHA" value="#{carteleraController.fechaConsulta}"
maxlength="10"
size="10"
locale="es"
pattern="dd/MM/yyyy"
navigator="true"
showOn="button"
showButtonPanel="true">
<f:converter converterId="calendarConverter" />
<p:ajax process="#this" update=":PAG_CARTELERA" event="dateSelect" listener="#{carteleraController.consultarOtroDiaAction}" />
In the "consultarOtroDiaAction" listener I set the "existeCookieCinePref" boolean field and return void to stay in the same view ("carteleraController" is a ViewScoped a bean).
However the first ajax request when I change the value of the p:calendar component works fine, but the following requests recreates the ViewScoped bean.
Why is this?
Thank you.
NOTE: If in the p:calendar ajax request I update a component of the carteleraOut.xhtml itself, it works, but if I update the whole PAG_CARTELERA panelgroup, it recreates the bean.
can you try h:panelGroup inside of h:form
<h:form id="FRM_CARTELERA">
<h:panelGroup id="PAG_CARTELERA" layout="block">
<h:panelGroup rendered="#{!carteleraController.existeCookieCinePref}">
<ui:include src="/paginas/cartelera/cinePreferidoIn.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{carteleraController.existeCookieCinePref}">
<ui:include src="/paginas/cartelera/carteleraOut.xhtml" />
</h:panelGroup>
</h:panelGroup>
</h:form>

rich:calendar not triggering f:ajax

I'm new to jsf, and I'm writing my first application using richfaces. I'm having trouble with the ajax tag that I use to update the associated managed bean property on server for rich:calendar components. This is the code:
<rich:panel header="Computing Options">
<h4>Time Interval</h4>
<h:panelGrid columns="4" width="100%">
<h:outputText value="From" />
<rich:calendar id="intervalFrom" value="#{scenarioEditor.intervalFrom}" popup="true" showApplyButton="true" datePattern="yyy-MM-ddTHH:mm">
<a4j:ajax execute="#this" event="change" render="outFrom" />
</rich:calendar>
<h:outputText value="To" />
<rich:calendar id="intervalTo" value="#{scenarioEditor.intervalTo}" popup="true" showApplyButton="true" datePattern="yyy-MM-ddTHH:mm">
<a4j:ajax execute="#this" event="change" render="outTo" />
</rich:calendar>
<h:outputText id="outFrom" value="From: #{scenarioEditor.intervalFrom}" />
<h:outputText id="outTo" value="To: #{scenarioEditor.intervalTo}" />
</h:panelGrid>
<h4>Algorithms</h4>
<h:panelGrid columns="2">
<h:selectBooleanCheckbox value="#{scenarioEditor.visibilityClashes}" id="clash" >
<f:ajax execute="#this"/>
</h:selectBooleanCheckbox>
<h:outputLabel value="Visibility Clashes Evaluator" for="clash" style="width:170px" />
<h:selectBooleanCheckbox value="#{scenarioEditor.xBandInterference}" id="xband" >
<f:ajax execute="#this"/>
</h:selectBooleanCheckbox>
<h:outputLabel value="X-Band Interferences Evaluator" for="xband" style="width:170px"/>
</h:panelGrid>
</rich:panel>
checkboxes works fine, but the calendars do not. Why? I`ve tried both f:ajax and a4j:ajax without luck.
To better clarify, I want that right after the user has finished entering a value into the calendar, an ajax request is made that call the setter method for the associated property. And this, for the calendar does not happen while for the checkboxes, it does.
The ajax event is failing because of T in datePattern="yyy-MM-ddTHH:mm" is not a valid date formatting pattern. If you add a <rich:messages/> component to your field, you'll see that a conversion error is occurring on each ajax request. Remove the T and you'll be fine

selectBooleanCheckbox ajax event fires but the listener is never executed

The selectBooleanCheckbox ajax event fires but the listener is never executed.
If I remove the c:forEach and just call the first one in the list it works.
<p:selectBooleanCheckbox value="#{Controller.graphFilter.get(0).checked}" >
<p:ajax listener="#{Controller.addMessage}" />
</p:selectBooleanCheckbox>
notes:
graphFilter is a list where container has the sets/gets for checked and description.
controller is a viewscoped managed bean.
addMessage public function that puts a message for the growl.
Everything is in the same form.
<h:form id="form" prependId="false">
<p:growl id="growl" showDetail="true"/>
<c:forEach items="#{Controller.graphFilter}" var="Gc">
<h:outputText value="#{Gc.description}" />
<p:selectBooleanCheckbox value="#{Gc.checked}" >
<p:ajax listener="#{Controller.addMessage}"/>
</p:selectBooleanCheckbox>
</c:forEach>
</h:form>
You should wrap your components with a p:column:
<p:column>
<h:outputText value="#{Gc.description}" />
<p:selectBooleanCheckbox value="#{Gc.checked}" >
<p:ajax listener="#{Controller.addMessage}"/>
</p:selectBooleanCheckbox>
</p:column>
But replacing the whole structure with a p:dataList would be more elegant.

understanding ajax execute behavior with datatable using jsf 2.0

i'm trying to use an search button which brings back the selected items (can be more than one) and it updates the datatable. Then i have a selectBooleanCheckbox next to each colomn, when user selects "n" items then presses the Select the checked Items it insert DB.
The code can be seen below:
<h:panelGrid columns="5">
<h:form>
<h:outputText value="Item Name"/>
<p:inputText value="#{StockController.itemName}"/>
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
//The code sample below belongs to BalusC see the post here
<h:panelGroup id="results">
<h:form>
<h:dataTable value="#{bean.entities}" var="entity">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[entity.id]}" />
</h:column>
...
</h:dataTable>
<h:commandButton value="Select the checked Items" action="#{StockController.insertDao}" >
<f:ajax execute="#form" render=":results"/>
</h:commandButton>
</h:form>
</h:panelGrid>
Now, i have read many blogs and Core javaServer Faces 3, i don't think there is logical error in ajax usage. I tested by removing each ajax then both works fine but whenever i try to use both of cummondButtons with ajax, the second one "Select the checked Items" does not even call the "StockController.insertDao" method.
Any help is appreciated.
Thanks all.
When you want to ajax-render content which in turn contains another form, then you need to include the ID of that form in the render attribute as well, otherwise the other form will lose its view state and nothing will be processed on submit.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results :resultsForm" />
</h:commandButton>
</h:form>
<h:panelGroup id="results">
<h:form id="resultsForm">
...
</h:form>
</h:panelGroup>
If there's however nothing which goes outside <h:form> inside the same <h:panelGroup>, then you can just omit the <h:panelGroup> altogether and re-render the form directly.
<h:form>
...
<h:commandButton value="Search" action="#{StockController.Search}">
<f:ajax execute="#form" render=":results" />
</h:commandButton>
</h:form>
<h:form id="results">
...
</h:form>
This is related to JSF spec issue 790.
See also:
Communication in JSF2 - Ajax rendering of content which contains another form

Rendering other form by ajax causes its view state to be lost, how do I add this back?

I have
<h:form>
<h:commandLink action="#{my_fake_ajax_link}">
<h:outputText value="Link" />
<f:ajax render=":mydiv" />
</h:commandLink>
</h:form>
<h:panelGroup layout="block" id="mydiv">
<h:form>
<h:commandLink action="#{mybean.delete(0)}">
<h:outputText value="Here" />
<f:ajax render="#form" />
</h:commandLink>
</h:form>
</h:panelGroup>
When I click once on "my_fake_ajax_link", then I have to click twice on "delete" link. This is only an example. I don't have this real case. I have multiple forms on a page and I can't just add all of them in a single form.
I checked what the problem is and it is:
When you click on "my_fake_ajax_link", the mydiv refreshs with ajax as it should.
ViewState of the refreshed form on ajax is missing.
How can I add the ViewState? How can I make it work without using only one form? This looks like an JSF bug to me. I don't want to refresh that div automatically with
jQuery("#mydiv").load(document.location.href);
but I will in my worst case possible.
This is a known problem in the auto-included jsf.js library of JSF which handles ajax responses. See also JSF spec issue 790 which is fixed in the upcoming JSF 2.3. In the meanwhile, with JSF 2.0/2.1/2.2, you have to explicitly specify the ID of the other <h:form> inside the render attribtue to trigger proper addition of the view state.
<h:form>
<h:commandLink action="#{my_fake_ajax_link}">
<h:outputText value="Link" />
<f:ajax render=":mydiv :mydivForm" />
</h:commandLink>
</h:form>
<h:panelGroup layout="block" id="mydiv">
<h:form id="mydivForm">
<h:commandLink action="#{mybean.delete(0)}">
<h:outputText value="Here" />
<f:ajax render="#form" />
</h:commandLink>
</h:form>
</h:panelGroup>
No, this does not cause any overhead or markup duplication in the ajax response. Alternatively, use OmniFaces fixviewstate.js.
See also:
Communication in JSF 2.0 - Ajax rendering of content which contains another form
h:commandButton/h:commandLink does not work on first click, works only on second click
Workaround for that:
First you need to set an onevent handler for the button that sends the ajax request:
<h:form id="newComment">
<h:commandButton id="saveNewComment" action="#{postBean.actionSaveNewCommentAjax}" value="#{rb['speichern']}">
<f:ajax execute="#form" render=":commentsBox" onevent="function(data) { fixOtherFormsViewState(data, 'newComment') }" />
</h:commandButton>
</h:form>
Then you need to declare this javascript methods that will take the correct viewState value and add it to all forms which doesn't have it:
<h:outputScript>
function fixOtherFormsViewState(data, goodFormId) {
if (data.status != "success") {
return;
}
var viewState = jQuery("#" + goodFormId + " input[name='javax.faces.ViewState']").val();
jQuery("form:not(:contains(input[name='javax.faces.ViewState']))").each(function (idx, elem) {
var form = jQuery(elem);
var input = jQuery("<input type='hidden' name='javax.faces.ViewState' />").val(viewState);
form.append(input);
});
}
</h:outputScript>

Resources