Get sibling element from PrimeFaces datatable row - jsf-2

I have a datatable created in PrimeFaces which receives and render a list of objects. At the end of the row I have a commandButton element and when it is used it do some stuff on the managedBean on the server.
All the data about the current row is retrieved using an object id placed in the command button in the param attribute.
The problem is that I have a selectOneMenu element and it is not related to the object. I select one value that affects the logic behind.
Here is the table:
<h:panelGrid id="panel" columns="2" bgcolor="#cce4ff"
cellpadding="10" cellspacing="1" rendered="#{indexBean.showChannelList}"
style="margin-top: 10px; margin-left: 100px;">
<p:dataTable var="program" value="#{indexBean.programList}" style="width:1000px;"
paginator="True" rows="10" rowIndexVar="row" sortBy="#{program.id}"
paginatorPosition="bottom" widgetVar="programDT" id="programDT">
... That the select
<p:column headerText="text" width="15%">
<h:selectOneMenu id="select-valability" value="#{indexBean.valabilitySelected}" disabled="#{indexBean.disabled}" style="font-size: small;">
<f:selectItems value="#{indexBean.listValabilities}" />
<f:param value="#{program.id}" />
<f:ajax resetValues="true" />
</h:selectOneMenu>
</p:column>
... and there is the command button
<p:column headerText="text" width="20%" style="text-align: center;">
<h:commandButton id="cmd-button-id" value="gen JSON" action="#{indexBean.action}"
style="width: 200px; height: 30px;"
class="ui-button ui-widget ui-state-default ui-corner-all"
>
<f:param name="programId" value="#{program.id}" />
</h:commandButton>
</p:column>
I want to be able to get the value of the select element from that specific row from which the action was triggered.
I've try with context.findComponent() but it gives me null even if I put the absolute path to the element with the index generated by JSF table as form:table:index:staticIdOfSelect.
I don't know how to get the sibling element. That was another though.
From the bean class:
#ManagedBean
#SessionScoped
public class IndexBean
I'm really stuck here.
Thanks in advance!

Use some element on the row to set an ajax listener in the bean to store the data and then update="the element" you want to get the information from.

Related

Could the setter be omitted in JSF

I'm using WildFly 8.0.2 along with primefaces 5.2, i have a p:datatable, with a column that have a p:inputSwitch, the value on this p:inputSwitch is a method (that return either true or false), so it does not have a setter method, i have attached a p:ajax to handle the switching event (on/off), but when i change the value it always raise an javax.el.PropertyNotWritableException: Illegal Syntax for Set Operation exception (cause the value is a method ... and has no setter).
here is my code:
<p:column styleClass="status #{employee.haveSkill(skill) == true ? 'have' : 'dosntHave'}">
<div style="text-align: center;">
<p:inputSwitch value="#{employee.haveSkill(skill)}" onLabel="#{msgs.yes}" offLabel="#{msgs.no}">
<p:ajax listener="#{skillsController.addSkill(employee, skill)}" />
</p:inputSwitch>
</div>
</p:column>
i have tried with a c:set, that stores the result of the method in a variable and then assign it to the p:inputSwitch component, but that didnt work for me, and the p:inputSwitch is always set to false (although the EL expression for the style class of the cell is working fine), here is the code that i have tried:
<p:column styleClass="status #{employee.haveSkill(skill) == true ? 'have' : 'dosntHave'}">
<div style="text-align: center;">
<c:set var="have" value="#{employee.haveSkill(skill)}" scope="request" />
<p:inputSwitch value="#{have}" onLabel="#{msgs.yes}" offLabel="#{msgs.no}">
<p:ajax listener="#{skillsController.addSkill(employee, skill)}" >
</p:ajax>
</p:inputSwitch>
</div>
</p:column>
So is there like a way to tell jsf or el not to fire the "set" method for that component? and just execute that listener on the ajax??
UPDATE:
I have also tried with the ui:param, but it also raises the javax.el.PropertyNotWritableException :
<p:column styleClass="status #{employee.haveSkill(skill) == true ? 'have' : 'dosntHave'}">
<div style="text-align: center;">
<ui:param name="have" value="#{employee.haveSkill(skill)}" />
<p:inputSwitch value="#{have}" onLabel="#{msgs.yes}" offLabel="#{msgs.no}">
<p:ajax listener="#{skillsController.addSkill(employee, skill)}" >
</p:ajax>
</p:inputSwitch>
</div>
</p:column>

Updating composite overlayPanel

Based on this subject, I would like to update a <p:overlayPanel> from a datatable to a composite component
View
<h:form id="myForm">
<p:dataTable id="myTable" ...>
<p:column headerText="1">
<p:commandLink id="link"
actionListener="#{bean.update}"
update=":toto" value="Val" />
<p:overlayPanel id="panel" for="link">
<my:view id="toto">
</p:overlayPanel>
</p:column>
</p:dataTable>
</h:form>
Composite
<composite:implementation>
<span id="#{cc.clientId}">
<p:dataTable id="toto" ...>
</p:dataTable>
</span>
</composite:implementation>
However I always get an error message saying that :toto component id can not be reached.
So, how can I access the dataTable placed in the composite ?
EDIT : Actually I changed my mind concerning the utilisation of p:overlayPanel for a p:datatable because of the creation of dynamic ids. I replaced this by a p:dialog and it works great.

Want to show a data table populated with data after a button click

I want to write a code in this way, that If I click on a button a data table appears populated with data. before that there should not be the data table in view.
<p:commandButton value="Go" styleClass="apply_button" actionListener="#{searchBean.getUserList}">
<f:attribute name="trigram" value="#{searchBean.trigram}"/>
<f:attribute name="firstName" value="#{searchBean.firstName}"/>
<f:attribute name="lastName" value="#{searchBean.lastName}"/>
</p:commandButton>
here the method getUserList() returns a list of data that should be populated in the data table.and it works.
<p:dataTable value="#{searchBean.listUser}" var="user">
<p:column headerText="Trigram">
<h:outputText value="#{searchBean.trigram}"/>
</p:column>
</p:dataTable>
It shows in the Data Table after I click on the button, But the Data Table appears before the button click with empty fields. How can I modify my codes to show make the Data Table appear after my button click?
Codes are within the <h:form> Tag.
And the Managed Bean searchBean is in #ViewScoped.
You can initialize a simple getter/setter :
private boolean visible = false; // getter/setter
public void getUserList(ActionEvent event)
{
setVisible(true);
// Your code
}
And modify your view like this :
<p:commandButton value="Go" styleClass="apply_button" actionListener="#{searchBean.getUserList}" update="table-wrapper">
<f:attribute name="trigram" value="#{searchBean.trigram}"/>
<f:attribute name="firstName" value="#{searchBean.firstName}"/>
<f:attribute name="lastName" value="#{searchBean.lastName}"/>
</p:commandButton>
<h:panelGroup id="table-wrapper">
<p:dataTable rendered="#{searchBean.visible}" value="#{searchBean.listUser}" var="user">
<p:column headerText="Trigram">
<h:outputText value="#{searchBean.trigram}"/>
</p:column>
</p:dataTable>
</h:panelGroup>
Note the update attribute on button, h:panelGroup wrapper and rendered attribute on table.

Primefaces component not refreshing

I have been looking at Primefaces 3.4.2 since IceFaces 3.2.0 has too many issues. I have a dataGrid of vehicles which are contained in a panel. I have an add button and each vehicle panel contains a remove button.
The add works fine; it adds a new vehicle panel each time. The issue is when I delete a vehicle, the panel is removed, but the value(s) remain. For instance, if I have 3 vehicles with the year as 2008, 2010, 2012, and then I delete the first vehicle, you'd think you would see 2 panels remaining with the year as 2010, and 2012. Instead, I see 2008 and 2012. The backing bean is doing it correctly and I do see the correct values if I manually refresh the screen. Now that I have presented my case here's the code:
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<ui:include src="../components/vehicleinfo/vehiclecomponents.xhtml">
<ui:param name="currentVehicle" value="#{currentVehicle}" />
<ui:param name="labelOnly" value="false" />
</ui:include>
<div class="deleteButton">
<p:commandButton value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update=":vehicleInfoForm:vehicleGrid" process="#this">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
Any ideas? I have tried all sorts of update values including #form, but it's all the same. I haven't used a dataGrid before but I need the iterative capabilities that ice:panelSeries has.
UPDATE: Here's the code in the include:
<h:panelGrid columns="2">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label=""
required="true" requiredMessage="VIN is required" >
<p:ajax update="#this vinMsg"/>
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
</h:panelGrid>
1/14/2013 - Updated code
<p:dataGrid id="vehicleGrid" var="currentVehicle" value="#{vehicleInfoBean.getVehicleList()}" columns="#{vehicleInfoBean.getVehicleList().size()}" styleClass="vehicleInfoPanel" rowIndexVar="rowIdx">
<p:panel header="VEHICLE ##{rowIdx+1}:" style="width:100%" styleClass="textEntryInputTable">
<h:panelGrid columns="1" style="width:100%" styleClass="vehicleInfoPanel">
<p:inputText id="vinInput" styleClass="stdFieldControl" value="#{currentVehicle.vin}" label="" required="#{empty param['vehicleGrid:0:btnDelete'] and empty param['btnAdd']}" requiredMessage="VIN is required" >
</p:inputText>
<p:message id="vinMsg" for="vinInput" errorClass="ui-state-error-text"/>
<p:outputLabel value="-----OR-----"/>
<h:inputText id="yearInput" styleClass="stdFieldControl" value="#{currentVehicle.year}" label=""
required="#{empty param['vehicleGrid:0:btnDelete']}" requiredMessage="Year is required">
</h:inputText>
<p:message id="yearMsg" for="yearInput"
errorClass="ui-state-error-text"/>
<div class="deleteButton">
<p:commandButton id="btnDelete" value="Remove" label="Delete Vehicle" action="#{vehicleInfoBean.deleteVehicle}" update="#form">
<f:setPropertyActionListener value="#{currentVehicle}" target="#{vehicleInfoBean.currentVehicle}" />
</p:commandButton>
</div>
</h:panelGrid>
</p:panel>
</p:dataGrid>
The add code looks like this:
<div class="addButton" style="padding-left: 2.17%; float: left; clear: both">
<p:commandButton id="btnAdd" value="AddVehicle" label="Add Vehicle" actionListener="#{vehicleInfoBean.addVehicle}" update="vehicleGrid"/>
</div>
Instead of putting the check on the buttons, I decided to set the required attribute of the components referring to the buttons. This code works if I hardcode the iterator index. For example, required="#{empty param['vehicleGrid:0:btnDelete']}". This code points to the first delete button in the panelGrid. What I need is to dynamically derive the index to this - required="#{empty param['vehicleGrid:#{rowIdx}:btnDelete']}". The add button was easy since it doesn't reside in an iterator. How do I code the param in a way that I can dynically refer to the rowId of the panelGrid? The RowId looks confusing but this is coded in a way that each Vehicle Panel is displayed next to the previous panel. The row in this case can be thought of as a column. Anyone have any ideas?

Conditional rendering of Checkbox not working in JSF

Presently I am conditionaly rendering the Checkbox inside outputPanel,but when i am selecting it,its value is not getting updated in the backing bean.Please help how can I fix this.
Please find the code below:
<p:outputPanel rendered="#{dataBean.dataCleanModel.checkThresholdValueForStdDev(o)}">
<td><h:selectBooleanCheckbox value="#{o.checkBoxToAcceptTheRow}"/></td>
</p:outputPanel>
<p:outputPanel rendered="#{!dataBean.dataCleanModel.checkThresholdValueForStdDev(o)}">
<td><h:selectBooleanCheckbox value="#{o.checkBoxToAcceptTheRow}" /></td>
</p:outputPanel>
As shown changing the checkbox value corresponding setter method is not getting invoked/changed value is not getting set in the bean
use <f:ajax/> if you want the check box to immediately set the value to the server
<h:form>
<p:outputPanel rendered="#{dataBean.dataCleanModel.checkThresholdValueForStdDev(o)}">
<td>
<h:selectBooleanCheckbox value="#{o.checkBoxToAcceptTheRow}">
<f:ajax/>
</h:selectBooleanCheckbox>
</td>
</p:outputPanel>
<p:outputPanel rendered="#{!dataBean.dataCleanModel.checkThresholdValueForStdDev(o)}">
<td>
<h:selectBooleanCheckbox value="#{o.checkBoxToAcceptTheRow}">
<f:ajax/>
</h:selectBooleanCheckbox>
</td>
</p:outputPanel>
</h:form>

Resources