Conditionally rendering a dataTable - ajax

I have a <rich:dataTable> in JSF page.
<rich:dataTable id="transactionTable" rendered="#{tellerBean.userTransactions.size() > 0}"
value="#{tellerBean.userTransactions}" var="transaction">
When I press a search button, the backing list gets filled and I re-render the table. However this does not work, because the rendered attribute is server side and the grid never gets converted to HTML in the first place so re-rendering fails. How can I have the grid to be hidden when the backing list is of 0 size, and shown when the list size is > 0?

Wrap it in a component which is always rendered and update it instead.
<h:panelGroup id="transactionTableGroup">
<rich:dataTable ... rendered="#{not empty tellerBean.userTransactions}">
</rich:dataTable>
</h:panelGroup>
(note that I improved the EL expression in the rendered attribute as well; yours was clumsy and would only produce a XML syntax error when using Facelets instead of legacy JSP)
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?

Related

JSF cannot update single form in ui:repeat from outside

I have two problems which are closely related:
I need to update a form inside a tag inside ui:repeat from a dialog at the main page and cannot figure out how (because there are many tags in the ui:repeat and I need to update only one)
naming containers are messed up and lose their "index" when I use id in that form (in case of trying to determine the update path expression...)
reason I need this: updating the 'wholelist' (current situation) breaks all <p:calendar> inside the <p:dialog> somehow (no errors...) (the calendar overlay shows at the first time, but after updating the list it does not appear any more (must reload page again). Also I don't want to update 100 elements each time if only one can be changed
page.xhtml
<h:panelGroup id="wholelist">
<ui:repeat var="entry" value="#{bean.foundEntries}" id="repeatId">
<customTag:someTag entry="#{entry}" />
</ui:repeat>
</h:panelGroup>
...
<p:dialog widgetVar="dialog" id="dialog">
<p:calendar value="#{bean.date}" ... /> <!-- overlay pops up on select until the whole list is refreshed. after that it does not appear until page reload -->
<p:commandButton actionlistener="#{bean.saveSomething()}" update="#{bean.componentToUpdate WHICH DOES NOT WORK...}"/>
</p:dialog>
someTag.xhtml
and within the <customTag:someTag> (which is a tag because of multiple reuses) :
...
<h:form>
... display a lot of data which can be changed by the dialog...
<p:commandButton value="show edit dialog" onComplete="PF('dialog').show()" update=":dialog">
<f:setPropertyActionListener value="??? (#form does not work)" target="#{bean.componentToUpdate}" />
</p:commandButton>
</h:form>
First Question:
I need to refresh one single form from the dialog (=the dialog which needs to know which form I want to refresh, and I have no idea how to do so...)
And how can I get the update-logic working (pass the component to update to the bean so the dialog knows what to update or equal)?
Second Question:
why does JSF generate in case of not defining a id="..." to a naming container within a ui:repeat something like
repeatId:0:j_id_c0_6
repeatId:1:j_id_c0_6
repeatId:2:j_id_c0_6
and when I define a id to the form (<h:form id="formname">) something like
repeatId:formname
repeatId:formname
repeatId:formname
which causes duplicateId (because the lack of the "iterator-number" in the name)?
Does this make sense?
I have solved it; error was elsewhere: I have forgotten in an included tag file which caused the js warning (which broke the calendar).
many thanks

Ajax update of non-JSF component with PrimeFaces selectors

Is it possible to update any html fragment using Primefaces selectors - PFS?
Consider this:
<h:outputText id="test" value="#{testBean.date}"/>
<span id="test2"><h:outputText value="#{testBean.date}"/></span>
<p:commandButton value="test" process="#none" update="#(#test)"/>
<p:commandButton value="test2" process="#none" update="#(#test2)"/>
Only first button is refreshing.
It's trival example - my real need is to update some parts of datatable, without refreshing whole component.
No, that's not possible. The update target must not only in client side be obtainable in HTML DOM tree by document.getElementById(), but also in server side by UIViewRoot#findComponent(), so that JSF can regenerate the desired HTML output which ultimately get applied during the ajax update.
If you supply JSF the ID of a plain HTML element, then it won't find anything in the component tree to regenerate the desired new HTML output for. Just replace the plain HTML element by a JSF component.
The PrimeFaces selectors get ultimately converted to HTML element IDs. PrimeFaces will loop over the elements found by the jQuery selector and extract their id attributes before passing to JSF. This is thus essentially the same problem as already answered here: Is it possible to update non-JSF components (plain HTML) with JSF ajax?.

Partial rendering redundant method call

I am aware that JSF may call a managed bean method a couple of times even if it is called only once in .xhtml. I understand that is due to encode* methods.
I would like to ask you to explain the following case to me.
I have a JSF file that sort of looks like this:
<h:form id="form1">
<h:panelGroup id="output">
...
<h:commandLink...>
<f:ajax render=":form1:output"/>
</h:commandLink>
</h:panelGroup>
</h:form>
All clear so far; pressing the command link rerenders a part of the page within the form panelGroup.
The code follows:
<ui:repeat value="#{movieBean.categories}" var="category">
<li>
<h:outputLink value="index.xhtml">
<f:param name="categoryId" value="#{category.categoryId}"/>
<h:outputText value="#{category.description}"/>
</h:outputLink>
</li>
</ui:repeat>
#{movieBean.categories} //this is just a 'test line'
movieBean is request scoped.
Now, when I enter the page for the first time I get two calls to movieBean.categories.
That is clear because it is called twice in the code. However, when I hit the AJAX link rendering
only a part of the page (output) I get movieBean.categories from <ui:repeat> called again even
though it is outside the partially rendered page area. The 'test line' is not called this time.
I performed another test. I deleted the <ui:repeat> tag leaving the 'test line' only.
AJAX partial rendering dosen't call it as before.
What makes the movieBean.categories call inside a <ui:repeat> tag different
than the one in 'test line'? And why is the call inside <ui:repeat> made when pressing the AJAX link
even though it is outside partially rendered <h:panelGroup id="output"/> tag?
I'm pretty sure that "redundant" call is made within a phase where JSF rebuilds element tree to store POST data into appropriate elements.
So you basically have two getter calls per request if you stay on the page. First one to store new form values, then to render page content.

JSF 2.0 - Ajax and Rendered Components

I'm experiencing some problems when using the "rendered" attribute with ajax behavior. I'll paste the code so I think it will be a lot more clear:
<h:selectOneMenu value="#{registrarVentaController.esCobroChequeString}">
<f:selectItem itemLabel="Efectivo" itemValue="false"/>
<f:selectItem itemLabel="Cheque" itemValue="true"/>
<f:ajax execute="#this" render="#form"/>
</h:selectOneMenu>
<h:panelGroup id="panelMonto">
<span>Monto:</span>
<h:inputText value="#{registrarVentaController.monto}" rendered="#{registrarVentaController.banCobroCheque}"/>
<h:inputText value="#{registrarVentaController.monto}" rendered="#{not registrarVentaController.banCobroCheque}"/>
</h:panelGroup>
My "#{registrarVentaController}" is just a View Scoped JSF Managed Bean with appropiate setters/getters.
This way it works, I mean, when user selects option "Efectivo", panelGroup "panelMonto" will get updated and we'll see the first inputText, and conversely when user selects option "Cheque" user will see the second inputText.
For this approach I used "f:ajax" component where I updated the whole #form to get this behavior work and I just want to update panelGroup "panelMonto" (using render="panelMonto" It doesn't work at all (I even try with full scope resolution :formName:panelMonto with no result).
I just want to have rendered work with ajax="idComponent" or similar behavior to show certain parts according what user have selected.
Best Regards!
Note (One solution)
I managed to get a solution (taking as an input
JSF rendered is not working
and a bit of myself). I've just moved to a new form the part that I'm
interested in filtering according what user selected. This way I still
use #form ajax's render and it will just render this new form (not the
whole form as I was using!) Neverthless I'm still wondering if there
is a solution to not used #form and just the component/s ID.
what if you check with
render=":panelMonto"
not
render=":formName:panelMonto"
still not working?
this should work only with
render="panelMonto" //because is in the same form
Can you add more code?
Also can you check with your browser (in chrome: right click, inspect element, network) to see if there is any activity?? perhaps is rendering the same thing because of you...

p:commandButton update doesn't work in ui:include

I want to update a part of a page by PPR.
This is the part of page that i want to update:
<h:panelGroup id="aggiungiAuto"
rendered="#{!autoBean.operazioneOk}">
<ui:include src="../component/aggiungi_auto.xhtml"/>
</h:panelGroup>
While this is the commandButton present in aggiungi_auto.xhtml
<p:commandButton value="Submit"
update="growl aggiungiAuto aggiungiFoto"
actionListener="#{autoBean.insert}"/>
Any Idea?
JS/Ajax works on the client side, not on the server side. JSF works on the server side, not on the client side. When you instruct JSF to not render the component to HTML, then nothing will be present in the client side, so JS/Ajax will be unable to locate the HTML element to refresh/update.
You need to wrap it in another <h:panelGroup>.
<h:panelGroup id="aggiungiAuto">
<h:panelGroup rendered="#{!autoBean.operazioneOk}">
<ui:include src="../component/aggiungi_auto.xhtml"/>
</h:panelGroup>
</h:panelGroup>
This way the <span id="aggiuniAuto"> is always present in the client side, so JS/Ajax will be able to update it with the new HTML data generated by JSF.
So I was having this kind of a problem with PrimeFaces (the above answer not being sufficient this time), and I also discovered a solution.
Part of the problem I think was that I was using ui:include recursively. For whatever reason, PrimeFaces was irrationally causing UI components to be bound to the backend data out-of-sync; e.g., when an "Add" button was clicked, a new value would be created in the UI, but then the data for it would be ripped out of the values for the section below, etc...
The explanation? "[O]n a viewscoped bean, a hidden field is added to the form to hold post-back data[;] if that field is not included with the process, then the bean will lose context." This particular problem is prevalent with ui:include recursion especially. Solution (all regarding the p:commandButton or other actionable component):
Ensure that update and process are pointing to a JSF component, not a regular HTML component.
update the next scope up if it breaks (goes out-of-sync with the binding).
Use styleClass's for update (not e.g. PF ID's or #this:#parent kind of stuff), so that jQuery is utilized instead of PF, e.g.: #(.fieldset-class).
process whatever scope is being updated. (This is needed for the post-back data so that the Bean keeps its context for the update...) process="#this" is not needed here, provided that the button is contained by the process value component.
For all buttons without validation wanted, set immediate="true".
If none of the above works (which happened with the Add buttons, probably due to ui:include recursion), set process="#this", immediate="true", and update="#none", and then oncomplete="remoteCommandName();", and have a p:remoteCommand instead with that name with the process, immediate, and update mentioned in the above points.
If none of the above works (which happened with some other buttons, probably due to being yet another layer deeper in the ui:include recursion)... wrap a h:panelGroup around the next c:forEach up and then update the PrimeFaces ID of that in the button itself while keeping its remoteCommand call afterwards, as specified above.
If none of the above works (which happened yet again to me)... Try the following code:
In the p:commandButton(s): oncomplete="$('.FixButtonSC').click();"
In the p:fieldset with a style class of FieldsetSC:
<!-- Fix (hidden) button. -->
<p:commandButton id="FixButton" styleClass="FixButtonSC"
process="#this" update="#(.FieldsetSC)" style="display: none;" />
Hope that helps...

Resources