JSF Rich scroallable Datatable Issue - jsf

In a scrollable datatable, which displays a collection of objects , I have to add one manual row as first row. That row contains inputText, through which user can able to enter some values and while hitting enter, those values will save and displays in bottom rows. I couldnt able to add this manual row as first row. Below is the current code.
<rich:scrollableDataTable value="{resultList}" var="result">
<rich:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{result.name}" />
</rich:column>
<rich:column>
<f:facet name="header">Category</f:facet>
<h:outputText value="#{result.category}" />
</rich:column>
</rich:scrollableDataTable>
The above code is for just displaying the values from the backend.

1) For that you have to use bind rich:scrollableDataTable with the instance of HtmlScrollableDataTable in the backing bean.
In backing bean, create instance of it with accessor methods & then you can initialize it accordingly by adding the inputText components. Add actionListeners to these input components & then in listeners, you can add these inputText values as outputText to the table again as rows accordingly.
2) Else you can use inputText rather then outputText & disabling the subsequent rows other then 1st, so only data may get displayed - preventing input.
<rich:scrollableDataTable value="{resultList}" var="result">
<rich:column>
<f:facet name="header">Name</f:facet>
<h:inputText value="#{result.name}" disabled ="#{!result.isFirstRow}"/>
</rich:column>
<rich:column>
<f:facet name="header">Category</f:facet>
<h:inputText value="#{result.category}" disabled ="#{!result.isFirstRow}"/>
</rich:column>
</rich:scrollableDataTable>
Backing Bean :
//---
public void initialize(){
resultList.add(new Result("", "", true)); // Setting 1st input row enabled
}
public void inputListener(ActionEvent event){
// appending object based on input to the resultList
resultList.add(new Result(inputName, inputValue, false));
// added a boolean field to identify rows added later & to make them enable/disable accordingly
}
//---
I am not familiar with Richfaces, but tried to achieve it, as I was doing it with IceFaces.

Related

Filter p:datatable by boolean column (checkbox)

I am trying to filter my primefaces datatable by a boolean column using a checkbox filter but unfortunately filtering in primefaces datatable seems it does not work with any type other than String, but there should be a workaround for this case.
datatable column
<p:column headerText="A_boolean_column" filterBy="#{myBean.myBoolean}" filterMatchMode="exact">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter" onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
<h:outputText value="#{myBean.myBoolean}"/>
</p:column>
where possibleAnswers variable is a list that has been initialized on init method of myBean with true && false values
#PostConstruct
public void init(){
this.possibleAnswers= new ArrayList<>();
possibleAnswers.add(true);
possibleAnswers.add(false);
}
I have similar working examples in my datatable with text values and are working perfectly. Of course I could do a workaround to fix my issue by converting the values from boolean ( true / false) into String ("true" / "false") ( or even write a custom function to check for equality)but I don't really like this solution and I would prefer any other out of the box solution ( perhaps a different filterMatchMode ? ).
I am using primefaces 7.0
Normally an input component has a 'value' attribute that is bound to a field (getter/setter) in a backing bean. The type of this field can be used to automatically convert the technical string of the http request to the correct java type. For a datatable filter this cannot be automatically done since there is no value attribute. Giving all components knowledge about all possible containers they can be used in is bad design. So the only and corrrect solution is to use an explicit converter.
Have a Look at the Implementation of the Status-Column in the PrimeFaces datatable filter showcase, as far as I see it it is exactly what you need
for Reference:
<p:column filterBy="#{myBean.myBoolean}" filterMatchMode="in">
<f:facet name="filter">
<p:selectCheckboxMenu label="BooleanFilter"
onchange="PF('mydatatable').filter()" styleClass="custom-filter">
<f:converter converterId="javax.faces.Boolean" />
<f:selectItems value="#{myBean.possibleAnswers}" />
<p:ajax update="#form" oncomplete="PF('mydatatable').filter();"/>
</p:selectCheckboxMenu>
</f:facet>
</p:column>

PrimeFaces dataTable convert values for showing in a view

I have a question based in the following situation.
I have a backing bean that create a matrix with ints, in rows, columns and cells (tablaBean). I have no problem displaying it in a jsf view. Each one of those ints, it´s an ID of differents objects. How can I do, if I want to show in my JSF view, instead of ints, some attributes of the objects?
This is my dataTable:
<p:dataTable var="rowName" value="#{tablaBean.rowNames}" rowIndexVar="rowIdx">
<p:column headerText="Alumnos:">
<h:outputText value="#{rowName}"/>
</p:column>
<p:columns var="colName" value="#{tablaBean.colNames}"
headerText="#{colName}" columnIndexVar="colIdx">
<p:panel>
<h:outputText value="#{tablaBean.data2D[rowIdx][colIdx]}"/>
</p:panel>
</p:columns>
</p:dataTable>
So for example:
tablaBean.data2D[1][1]=3
But I don´t want to show the number "3" in my view.
I want to take that number and show the Person.name of my object Person.id=3;
Hope my question is clear enough.
Create in your backing bean method returning person name:
public String getPersonNameById(int idPerson) {
return myDao.findPersonById(idPerson).getName();
}
Use it in xhtml:
<h:outputText value="#{tableBean.getPersonNameById(tablaBean.data2D[rowIdx][colIdx])}"/>

Data Table row selection(single) in Primefaces 3.5 selects all rows

I need to add and remove rows in DataTable and using buttons to add and remove the rows respectively by single selection.
My html/jsf code is :
<p:dataTable id="creditTable" rowIndexVar="sn"
value="#{cpeTrainingMB.cpeTrainingObj.cpeTrainigSchDetail}"
var="cpeDetail" scrollable="true" scrollHeight="100"
selectionMode="single"
rowKey="#{cpeDetail.id}">
<p:ajax event="rowSelect" update=":cpe:creditTable" listener="#{cpeTrainingMB.onRowSelect}"/>
<p:column headerText="Sn">
<h:outputText value="#{sn+1}"></h:outputText>
</p:column>
<p:column headerText="Date">
<h:outputText value="#{cpeDetail.fromDtBS}"></h:outputText>
</p:column>
<p:column headerText="Credit HR">
<h:outputText value="#{cpeDetail.creditHr}"></h:outputText>
</p:column>
</p:dataTable>
The problem is that when I add more than one data, and then select a row to delete , it selects all the rows at once which is not required.
It works well for only one row.
The backing methods/functions are listed below :
public void onRowSelect(SelectEvent event){
cpeScheSelected = null;
this.cpeScheSelected = (CPETrainingScheduleModel)event.getObject();
cpeTrainingScheObj = null;
cpeTrainingScheObj = this.cpeScheSelected;
}
All elements listed in the dataTable must have a not-null value in the rowKey property (in this case - id field). Nulls will lead to the behaviour described in the question. An alternative to specifying rowKey is implementing SelectableDataModel with custom method public Object getRowKey(RowClass rc).

Check box and Radio Button selection gets cleared on h:selectOneMenu value change

I am working on a form which has two datatables. In the first datatable, I am displaying the radio buttons and checkboxes, whereas the second datatable contains
selectOneMenu(s). Value change listener has been implemented on the selectOneMenu and on value change, the subsequent fields gets populated based on the selection.
Everything works fine except that when I select the value from the dropdown, the checkbox and the radio button values are cleared.
f:ajax event="change" has been used for the change event on selectOneMenu. Looks like the whole page gets refreshed and the values are cleared.
I also tried using f:ajax by updating the id of the datatable in which the selectOneMenu is present.
<p:dataTable styleClass="borderless" id="inResultTable" var="result" value="#{RequestBean.fooFields}" rendered="#{not empty RequestBean.fooFields}">
<p:column style="width:150px;">
<f:facet name="header">
<h:outputText value=" " />
</f:facet>
<h:outputText value="#{msg[result.fldLabel]}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="" />
</f:facet>
<ui:repeat value="#{RequestBean.fooFields}"
var="itm">
<h:selectOneMenu value="#{itm.indFieldValue}"
rendered="#{result.lvlid==itm.lvlid}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneMenu>
<h:selectOneRadio value="#{itm.indFieldValue}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='radio'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectOneRadio>
<h:selectManyCheckbox value="#{itm.indFieldCheckBox}" rendered="#{result.lvlid==itm.lvlid and result.fldType=='selectbox'}">
<f:selectItems value="#{RequestBean[itm.indField]}" />
</h:selectManyCheckbox>
</ui:repeat>
</p:column>
</p:dataTable>
<p:dataTable styleClass="borderless"
id="resultTable" var="result"
value="#{RequestBean.depFields}">
<h:selectOneMenu value="#{RequestBean.field4Value}"
valueChangeListener="#{RequestBean.processValueChange4}"
rendered="#{result.lvlid=='5' and result.fldType=='selectbox'}"
style="width:250px;padding-right:150px;text-align: left;">
<f:selectItem itemLabel="--Please Select--" itemValue="#{null}" />
<f:selectItems value="#{RequestBean[result.field]}" />
<f:ajax event="change" render="#form" />
</h:selectOneMenu>
...
...
</p:dataTable>
N.B: The requirement is such that the datatable with checkbox and radio buttons has to be placed at the top. IDs cannot be used for the selectOneMenu in the second table since I am
populating the selecOneMenu(s) dynamically based upon the entries in the database.
I know that this might be a simple issue but didn't have any luck with the info posted on most websites.
Any help would be appreciated.
Here's your <f:ajax>.
<f:ajax event="change" render="#form" />
You didn't specify the process attribute. So it defaults to #this, which means that only the current input component is processed during submit. However, you specified a render of the whole form. So the whole form will be refreshed. However, the other input components aren't been processed during submit. So their model values won't be updated, which means that during render response the initial values will be redisplayed instead of the submitted values, which are in your case apparently blank/null.
You've basically 2 options:
Process the whole form during submit.
<f:ajax process="#form" render="#form" />
Or, update only those components which really needs to be updated.
<f:ajax render="clientId1 clientId2 clientId3" />
In your particular case I think option 2 isn't viable, so option 1 is the best one. Please note that I omitted the event attribute. It defaults to change already.
Unrelated to the concrete problem, I'm not sure what you're all doing in your value change listener method, but I only want to note that most starters abuse it for the purpose of manipulating the model values and that it don't always work quite as expected (changed model values are not reflected at all). If this is true in your case, then you should actually be using <f:ajax listener> instead.
See also:
When to use valueChangeListener or f:ajax listener?
The main reason for the values of Check boxes & Radio buttons getting cleared after a value change listener could be that the model values are not updated.
Value change listeners are called before updating the model.
For these kind of issues, it is very important to have an understanding of the JSF lifecycle.
Please try following code in your value change listener and see.
public void valueChange(ValueChangeEvent event){
PhaseId phase = event.getPhaseId();
if (phase.equals(PhaseId.ANY_PHASE))
{
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
return;
}
if(!phase.equals(PhaseId.UPDATE_MODEL_VALUES))
{
return;
}
// Your code
}
I didn't try this code with your example. Please let me know with complete example source code if it is not working.
Thanks.

Value of <h:selectBooleanCheckbox> inside <p:dataTable> remains false on submit

I have a primefaces datatable and inside the primefaces datatable, I have a column, which contains the . The issue is,I have set the default value for the as false. When I click/check the , its still retrieving the value as false. I tried it multiple times but not sure why its returning false. Please find the sample code below.
<p:dataTable id="review-table" var="item" value="#{demandBean.filterVOList}">
<p:column id="SelectallID" style="text-align: left; width:40px;" rendered="#{demandBean.screeRenderVo.selectAllRenderer}">
<f:facet name="header" >
<h:outputText id="selectId" value="#{demandBean.dmdScreenLabelVO.selectAll}" />
<div></div>
<h:selectBooleanCheckbox id="checkbox1" value="Select All" onclick="checkAll(this)"/>
</f:facet>
<h:selectBooleanCheckbox id="checkbox2" value="#{item.selected}"/>
</p:column>
Im getting the value as false, when I check the and click on the save button. I have written an Action listerner, below is the code corresponding to the actionListener
public void saveData(ActionEvent event)
{
System.out.println("Entering the Save :");
selected = isSelected();
System.out.println("value of Selected"+selected);
}
I have tried debugging the code as well, but not sure why the value for is getting displayed as false. Please Assist. Thanks in Advance
You seem to be binding the value of all checkboxes in the column to the one and same bean property. This way the value will ultimately end up to be the one of the last row in the column.
This is not how it's supposed to be used.
You basically need to bind the value of the checkbox to the property of the currently iterated row object (the one behind the var attribute of the datatable).
<p:dataTable value="#{bean.items}" var="item">
<p:column>
<p:selectBooleanCheckbox value="#{item.selected}" />
Alternatively, you could use the <p:column selectionMode="multiple" /> to use builtin multiple selection support of the PrimeFaces datatable (see also the showcase example).
<p:dataTable value="#{bean.items}" var="item" rowKey="#{item.id}" selection="#{bean.selectedItems}">
<p:column selectionMode="multiple" />

Resources