Update sibling component in JSF 2 / Primefaces - jsf-2

I have the following component tree on my page
form
tabView
datatable
dialog
Now I want to update the dialog component when a row is selected in the datatable.
I tried something like:
<p:ajax event="rowSelect" update="#parent:detailsView" oncomplete="detailsViewDialog.show()" />
where detailsView is the id of a panelGroup within the p:dialog.
Only having update="#parent" works but is it not a solution to always reload the whole table only to display the dialog.
Can anybody give me a hint?
Regards,
Florian

The data table is by itself a NamingContainer component, so it's hard to use a relative client ID. You'd basically need to specify the absolute client ID:
<p:ajax ... update=":formId:tabViewId:detailsView" />
Alternatively, you could also bind the UIComponent with ID detailsView to the view by binding attribute and use UIComponent#getClientId() in the update attribute:
<p:ajax ... update=":#{detailsView.clientId}" />
...
<h:panelGroup id="detailsView" binding="#{detailsView}">

Related

How to hide components by selecting a new value on h:selectOneMenu?

I have a page with a h:selectOneMenu, and I want to hide a dataTable when I choose a new value on the h:selectOneMenu while some bean attribute values update. I'm trying diferent things, and I'm able to hide the dataTable by reloading the page. I have tried this using some JavaScript code, on onsomething attributes. In that case, those bean attribute values disapear although I use t:saveState (and I also need the view scope for the bean).
Here is a little example to clarify this:
<h:selectOneMenu id="list" value="#{Bean.id}">
<f:selectItems value="#{Bean.List}" var="element" itemLabel="#{element.name}" itemValue="#{element.id}"/>
<t:saveState value="#{Bean.id}"/>
<f:ajax listener="#{Bean.populateBean}" render=":form:period" event="change"/>
</h:selectOneMenu>
<h:selectOneMenu id="period" value="#{Bean.period}">
<f:selectItems value="#{Bean.listaPeriod}" var="period" itemLabel="#{period[1]}" itemValue="#{period[0]}"/>
<t:saveState value="#{Bean.period}"/>
</h:selectOneMenu>
<h:commandButton id="search" action="#{Bean.doSearch}"></h:commandButton>
<t:dataTable id="data" value="#{Bean.configList}" rendered="#{Bean.search}"
<t:column>
...
</t:dataTable>
And Bean.doSearch changes Bean.search to true. How can I hide the dataTable when I choose a new value on h:selectOneMenu id="list"?
EDIT:
In short, the search button renders the table, and I would want to hide that table when I just choose a new value on the "list" dropdown without reloading the page. Now, the <f:ajax> is used only to rerender the "period" dropdown value.
Thanks in advance!
Your question is hardly understandable, but if you want to kick the datatable out of your view on ajax request triggered by your dropdown, you need to enclose it in a component that's always present in the view so that HSF would know what to rerender when ajax call successfully finishes:
<h:panelGroup id="rerender">
<t:dataTable rendered="#{bean.condition}" ...>
....
</t:dataTable>
<h:panelGroup>
Of course, to get it working you should specify id of the component to be rerendered:
<h:selectOneMenu ...>
...
<f:ajax listener="#{bean.populate}" render="rerender" />
</h:selectOneMenu>
Note that if both dropdown and datatable components belong to the same form, it's not necessary to specify absolute id of the latter's parent. Also note that specifying event is redundant, as it already defaults to the right one. Finally, as you're on JSF 2.x, using save state is not necessary, just bind the values of your form data to a view scoped bean.
The last thing to note is the fact that you fail to conform to the Java Naming Conventions, the thing you should correct as soon as possible.

Primefaces selectors not updating a panelGroup

I am trying Primefaces selectors and it appears that it couldn't update an panelGroup.
<h:panelGroup layout="block" styleClass="updateMe">
<h:outputText value="#{bean.value}"/>
</h:panelGroup>
<h:form>
<h:inputText value="#{bean.value}"/>
<h:commandButton value="submit">
<p:ajax process="#form" update="#(.updateMe)" oncomplete="alert(1)"/>
</h:commandButton>
</h:form>
In this case the panelGroup never gets updated. But if I change the panelGroup to <p:outputPanel>, then it worked fine.
Observing the generated HTML, the only difference is that the <span> generated by panelGroup doesn't have an id while the one generated by outputPanel has an id. Could this be the reason why the first one is not getting updated (cos jQuery selector couldn't find the component id?)
If that is the case, is there any other component that does not have any ids and should be avoided when using Primefaces selectors?
When using Primefaces selector jQuery is used to select components on client side, and discover their client ids. When AJAX is sent one of parameters that is sent is javax.faces.partial.render whose value are client ids of components which should be updated. If component doesn't have client id it can't be updated directly, you can update parent component for example. Provide id attribute for panelGroup and try to update it with Primefaces selector.

How to make p:selectOneMenu show current value?

I have a <p:selectOneMenu> to choose the category for an item from. By default the menu displays the first entry of someBean.selectedParty.categories as selected. But the item already has a current category at someBean.selectedItem.category that I want to be displayed/selected. How can I achieve that?
<p:selectOneMenu value="#{someBean.selectedItem.category}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{someBean.selectedParty.categories}" var="category" itemLabel="#{category.name}"/>
</p:selectOneMenu>
As long as the getter for someBean.selectedItem.category returns a value available in the list , it will show the value as selected.
However there are some gotchas:
1) The default value probably should be set in the bean constructor
2) The bean (someBean) cannot have the RequestScope - As every single HTTP request, including Ajax requests, would create a completely brand new instance of the bean with all properties set to default. If your bean is RequestScope, change to ViewScope
3) As you are "cascading" from someBean to selectedItem to category, note that the selectedItem and selectedParty must be the same through (not only same content but also same memory adress) or the lifecycle of JSF will stop. I guess you are setting the selected objects earlier. If you are using AJAX, try to post a "full" request to a new page with the drop-down to debug this.
4) To simplify this, you could try to move the category and categories directly into someBean so the page should look like
<p:selectOneMenu value="#{someBean.category}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{someBean.categories}" var="category" itemLabel="#category.name}"/>
</p:selectOneMenu>

PrimeFaces f:setPropertyAction with dataTable works only after a row is selected

Here is my Problem:
Backing bean is #SessionScoped
I have a p:dataTable with selectionMode set to single and selection #{bean.selectedCar}
first column in the table is a commandLink that updates a dialog :detailDialog, oncomplete shows the dialog and has an actionListener that hast to clear some property in the bean
f:setPropertyListener has a value #{item} and target #{bean.selectedCar}
I want that the user is able to click the link and the dialog will display the information for the object on the row, but it works only if a row in the dataTable was selected first. If no row was selected and the user clicks on the commandLink NULL is passed to the bean.selectedCar and the page hangs.
As a workaround I would like at least to be able to preselect the first row in the dataTable and hopefully this will do the trick.
You can re-use your f:setPropertyListener in your command link:
<p:commandLink value="show"
actionListener="#{bean.doSomething}"
oncomplete="dialog.show()">
<f:setPropertyListener value="#{item}" target="#{bean.selectedCar}"/>
</p:commandLink>
alternatively (since we are iterating through a dataTable) you can pass the current #{item} object to your <p:commandLink.../>:
<p:commandLink value="Show"
action="#{bean.selectThisCar(item)}"
oncomplete="dialog.show()"/>
Thanks #akoskm for your answer. The first variant was that what I used for the button. My problem was that (as the second option) this method conflicted with the selection option in the dataTable. Removing the selection="#{bean.selectedCar}" from the p:dateTable parameters was the salution of my problem. Thanks for the help.

Using <p:commandLink> on a cell in a datatable to open a subtable

I basically have a datatable in which one of the columns is clickable. I have done this by using the commandlink from primefaces.
Everywhere people have used this only to navigate, but I want the click to result in opening a sub datatable. Depending on which row I click on in that column the corresponding datatable must appear.
Can this be done using in primefaces, if so how do I proceed?
Thanks
I finally resolved this problem. I basically created one datatable and hid it, depending on the column clicked I used the backing bean to populate the datatable accordingly.
I made the onclick event call a function in the backing bean using the following code:
<p:column headerText="Train" style="font-size:90%;font-family:Times New Roman, Times, serif;">
<p:commandLink onclick="javascript:ShowHide('HiddenDiv');"
id="tableUpdater" update=":closeButton,:subForm:trainTable" value="#{rail.trainNo}"
action="#{yardMaster.populateTrainDetails(rail.trainNo)}"
style="font-family:Times New Roman, Times, serif;">
</p:commandLink>
</p:column>
So basically something like a dynamic datatable.

Resources