How to bind List of List in jsf datatable - jsf

Hi I have a variable like
List<List<MyObject>> x = new ArrayList<List<MyObject>>();
I wanted this bind to a datatable in jsf which contains select
<datatable>
<column>
<Select/>
</column>
</datatable>
Is this possible in jsf
Code:
view.xhtml
<h:dataTable id="i1" value="#{bean.listoflist}" var="list1">
<h:column>
<h:selectOneListbox value="#{bean.somestring}" >
<f:selectItems value="#{list1.?}" var="any" itemValue="#{any.??}/>"
</h:selectOneListbox>
</h:column>
</h:dataTable>`
Bean.java (name = "bean")
public class Bean implements Serializable
{
List<List<MyObject>> listoflist = new ArrayList<List<MyObject>>()
//--------------Getters and Setter
}
MyObject.java
public class MyObject
{
private String s1;
private String s2;
//---------------getter and setter
}

If I understood your problem properly, you want to make a datatable of select elements whose options come form the nested list of your model. If yes, here is the solution:
prepare an array of selected elements per the size of the outer list;
have a converter for your model object;
fill the UI components accordingly.
Below you may find a working example:
<h:dataTable value="#{bean.listOfLists}" var="list" binding="#{table}" >
<h:column>
<h:selectOneListbox value="#{bean.selection[table.rowIndex]}" converter="myObjectConverter" >
<f:selectItems value="#{list}" var="obj" itemValue="#{obj}" itemLabel="#{obj.s1}" />
</h:selectOneListbox>
</h:column>
</h:dataTable>
with
MyObject[] selection = new MyObject[listOfLists.size()];

Related

How to insert PrimeFaces p:selectManycheckbox value to database

I am new to primefaces and i have a problem to save my primefaces SelectManyCheckbox value to database. I am using hibernate and mysql. The sample code are give as below
My xhtml pages code is:
<h:outputText value="#{msg['elicense.examinationform.personal.classofcertificates']}"/>
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedClass}" layout="grid" columns="1">
<f:selectItems value="#{examinationFormBean.examinationPart}"var="className" itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
My bean is:
private String[] selectedClass;
private List<CertificateClass> examinationPart=new ArrayList<CertificateClass>();
getter()
setter()
The method where I want to save my checkbox is:
private void saveExaminationDetails()
{
examDetails.setElementaryPrinciples(); //bolean field
examDetails.setLightinig()
//no of setter
}
I am not able to find out how I will set the selected and not selected checkbox value on the method
Look at primefaces showcases: http://primefaces-rocks.appspot.com/ui/selectManyCheckbox.jsf
Selected values from examinationFormBean.examinationPart should setting in p:selectManyCheckbox attribute value and then you can used this selected list in bean method.
For your example should be something:
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedExaminationParts}" layout="grid" columns="1">
<f:selectItems value="#{examinationFormBean.examinationParts}" var="className" itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
And then you can use selectedExaminationParts in your saveExaminationDetails()
The p:selectManyCheckbox select values are biding a String Collection(List, ArrayList... etc) on managed bean. You just need to save each String existent on the Collection.
I will give you an example showing how you can do that:
Example:
...
#Named(value = "myBean")
#SessionScoped
public class InscricaoBean implements Serializable {
...
private List<String> selectedElemnts = new ArrayList();
//selectedElements get and set
...
On JSF you have something like:
...
<h:outputText value="#{msg['elicense.examinationform.personal.classofcertificates']}"/>
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedElemnts}"...>
<f:selectItems value="#{examinationFormBean.examinationPart}"var="className"
itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
...
On save method:
...
private void saveExaminationDetails()
{
for (String nameAux: selectedElemnts )
{
//you save the data here
}
}
...

JSF h:selectOneMenu is never set even when using f:ajax

I want to implement a filtering facility in a JSF web application as follows: The users can add as many filters as they want. They can also delete them. So I am having a dataTable of filters. Each row consists of one h:selectOneMenu which has an ajax “change” event in order to make a second h:selectOneMenu visible in the same row. The options of the second h:selectOneMenu are calculated dynamically according to the selected option of the first.
The problem is that the value of second h:selectOneMenu is never set to the back-end object even if I added an ajax event. However the value of the first h:selectOneMenu is set.
I have the following fragment of code in an .xhtml page:
<h:form id="filterForm">
<h:dataTable id="filterTable" value="#{filterManager.filters}" var="filter">
<h:column>
<h:outputLabel value="#{msgs.filterBy}:" for="availableFilters" />
<h:selectOneMenu id="availableFilters" value="#{filter.filter}">
<f:selectItems value="#{filterManager.getProperties(typeSelector.typeSelected)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:panelGroup id="filterValuesPanel" >
<h:outputLabel value="#{msgs.value}:" for="filterValues" rendered="#{!filter.filterEmpty}" />
<h:selectOneMenu value="#{filter.value}" id="filterValues" rendered="#{!filter.filterEmpty}" >
<f:selectItems value="#{filterManager.getPossibleAnswers(filter)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:panelGroup>
</h:column>
<h:column>
<h:commandButton value="#{msgs.delete}" title="#{msgs.deleteFilter}">
<f:ajax event="click" listener="#{filterManager.removeFilter(filter)}" render=":filterForm" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="#{msgs.addNewFilter}">
<f:ajax event="click" listener="#{filterManager.addNewFilter}" render=":filterForm" />
</h:commandButton>
</h:form>
I have a bean called “FilterManager” which has a ViewScoped. Important parts are shown below:
#ManagedBean
#ViewScoped
public class FilterManager implements Serializable {
private List<Filter> filters; // it has a getter
private int currentFilterId;
public void addNewFilter(AjaxBehaviorEvent event) {
this.currentFilterId++;
this.filters.add(Filter.getEmptyFilter(this.currentFilterId));
}
public void removeFilter(Filter filter) {
this.filters.remove(filter);
}
...
}
The Filter class is a normal class (not a bean) and is shown below:
public class Filter implements Serializable {
private int id;
private String filter;
private String value;
public String getFilter() {
return filter;
}
public void setFilter(String theFilter) {
if (theFilter != null && !theFilter.isEmpty())
this.filter = theFilter;
}
public String getValue() {
return value;
}
public void setValue(String theValue) {
this.value = theValue;
}
public boolean isFilterEmpty() {
return this.filter == null || this.filter.isEmpty();
}
...
}
Notice that TypeSelector is a SessionScoped bean which has a typeSelected property along with getter and setter.
The problem is: filter.filter is set correctly whereas filter.value is never set. I can't find the problem so I need your help please. Apologies for all this code but I needed to provide you with all the necessary details.
Thanks in advance!
Okay guys that was my fault. I had a bug in FilterManager.getPossibleAnswers(Filter filter) method. Basically, at the end of the method, I was setting filter.value to the first element of List unconditionally. Eg instead of writing
if (filter.getValue() == null || filter.getValue().isEmpty()) {
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
}
I just wrote:
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
Although filter.value was updating as normal, the value was changing back to default (first element in list) during re-rendering of dataTable component.

JSF datatable: adding and removing rows clear rows values

I have a h:datatable showing a list of rows, and the fields of each row are input fields.
I render an "Add Row" button before the table, and a "Remove Row" button on each row of the table.
The baking bean is viewScoped, and the buttons add/remove elements from the java list in the backing bean, and then return to the same view.
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
Everything works ok but one thing: the values of the input fileds are cleared. I thought that the view kept the values beacuse the bean is viewScoped.
How can I achieve adding/removing rows without triggering validations and keeping the values that were already typed by the user in the form?
My view:
<h:form>
<h:commandButton value="Añadir Fila" immediate="true" action="#{tablaController.addRowAction}" />
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" immediate="true" action="#{tablaController.removeRowAction(fila)}" />
</h:column>
</h:dataTable>
</h:form>
My backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
boolean exito = this.lista.remove(f);
return "";
}
...
}
UPDATE --> MY SOLUTION:
I write here my solution if someone is interested.
The problem is that I use immediate="true" to skip validations, but this makes to skip the update_model_values too, so that the values entered by the user in the form are lost after clicking the add/remove buttons and re-redenring the page.
As I use "JSR-303 bean validation", my solution was to skip validations using the f:validateBean to enable/disable them. Depending on the button I click, if I want the validations to execute, I enable the bean validation (for example in a "submit" button), and if I want to skip them, I disable bean validation (like in the add/remove row buttons). But anyway the update_model_values always executes, so the values are not lost.
Here's the view:
<h:form>
<f:validateBean disabled="#{!empty param['disableValidation']}">
<h:commandButton value="Añadir Fila" action="#{tablaController.addRowAction}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
<h:dataTable value="#{tablaController.lista}" var="fila" cellpadding="0" cellspacing="0" border="1">
<f:facet name="header">TABLA</f:facet>
<h:column>
<f:facet name="header"><h:outputLabel value="NOMBRE" /></f:facet>
<h:inputText id="nom" value="#{fila.nombre}" />
<h:message for="nom" class="msjError" />
</h:column>
<h:column>
<f:facet name="header"></f:facet>
<h:commandButton value="Quitar Fila" action="#{tablaController.removeRowAction(fila)}">
<f:param name="disableValidation" value="true" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{tablaController.saveData}" />
</f:validateBean>
</h:form>
The backing bean:
#ManagedBean(name="tablaController")
#ViewScoped
public class TablaController {
private List<Fila> lista;
...
public TablaController() { }
...
#PostConstruct
public void init() {
this.lista = new ArrayList<Fila>();
for (int i=0; i<5; i++) {
Fila fila = new Fila();
fila.setNombre("fila "+i);
this.lista.add(i,fila);
}
}
...
public String addRowAction () {
Fila fila = new Fila();
fila.setNombre("");
this.lista.add(fila);
return "";
}
public String removeRowAction (Fila f) {
this.lista.remove(f);
return "";
}
...
public String saveData () {
...
//processes the valid data
//for example, calls to a service method to store them in a database
...
return "";
}
...
}
I set the immediate attribute to "true" in the buttons in order to not validate the input fields when I add or remove a row.
immediate="true" is the wrong tool for the job. It should be used to prioritize validation, not to enable/disable validation. The difference is rather huge as you encountered yourself.
You want to trigger validation conditionally. In case of e.g. required="true" that'd be as easy as
<h:inputText ... required="#{saveButtonPressed}" />
where #{saveButtonPressed} evaluates true when the save button is pressed. E.g. when its client ID is present in request parameter map.
In case of JSR 303 bean validation, that'd be a matter of
<f:validateBean disabled="#{not saveButtonPressed}">
<h:inputText ... />
</f:validateBean>
or with OmniFaces <o:validateBean> which allows controlling that on a per-command basis.
<h:commandButton id="add" ...>
<o:validateBean disabled="true" />
</h:commandButton>
I had exactly the same problem. In short, you can NOT use immediate for action that update data table(UIData) or facelet repeat. Short explanation:submitted values are not kept for re-display if inputs in UIData do not go through validation. Long explanation can be found here: long explanation and a related bug in Mojarra

h:selectOneMenu in loop

I want to remember values from multiple h:selectOneMenu component in c:forEach loop. Now only last value from h:selectOneMenu is remember. I don't know how many h:selectOneMenu will appear.
<h:panelGrid
id="wynik"
columns="2"
border="0"
cellpadding="2"
cellspacing="0"
rowClasses="jsfcrud_odd_row,jsfcrud_even_row"
rules="all"
style="border:solid 1px">
<h:outputText id="ns" value="Numer stanowiska"/>
<h:outputText id="kontr" value="Kontroler"/>
<c:forEach
var="stanowisko"
begin="1"
end="#{stojakiController.selected.iloscstanowisk}"
step="1">
<h:column>
<h:outputText value="#{stanowisko}"/>
</h:column>
<h:column>
<h:selectOneMenu
id="kontroler_#{stanowisko}"
value="#{wyposazenieStojakaController.selected.kontroler}"
title="#{bundle.CreateWyposazenieStojakaTitle_kontroler}"
required="true"
requiredMessage="#{bundle.CreateWyposazenieStojakaRequiredMessage_kontroler}">
<f:selectItems value="#{kontroleryController.itemsAvailableSelectOne}"/>
</h:selectOneMenu>
</h:column>
</c:forEach>
</h:panelGrid>
This is not the right way to render a table based on a dynamically sized collection. You're binding the value of each row to one and same backing bean property. This property would get overwritten every time whenever each row needs to set the value. That's why you end up with only the value of the last row.
You should be using <h:dataTable> instead, not a <h:panelGrid> with a <c:forEach>. You should be preparing a collection of concrete model objects, not only the size of objects. For example,
public class Item {
private String value;
// ...
}
Then, in the (post)constructor of the backing bean you should prepare as many as necessary.
public class Bean {
private List<Item> items;
#PostConstruct
public void init() {
items = new ArrayList<Item>();
for (int i = 0; i < yourDesiredAmountOfItems; i++) {
items.add(new Item());
}
}
// ...
}
And here's a basic kickoff example how you should use it:
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:selectOneMenu value="#{item.value}">
<f:selectItems value="#{bean.availableValues}" />
</h:selectOneMenu>
</h:column>
</h:dataTable>
When you submit the form, JSF will set the value of each row rightly in each separate item object associated with the row.

Editable Datatable using a Dialog in JSF 2.0

I am currently running my web application in JSF 2.0, It also is using Primefaces 2.2RC2.
I know that primefaces gives you the ability to have editable rows, but for my project I would prefer if a user clicks on a commandButton within the table that a dialog is displayed prepopulated with that particular rows values and the user can edit the row that way.
The only way I have gotten this to work is to in the column that contains the commandButton, pass that rows contents as params like the example below:
<p:dataTable var="car" value="#{myBean.cars}" id="carList">
<h:column>
<h:inputText value="#{car.id}" style="width:100%"/>
</h:column>
<h:column>
<h:inputText value="#{car.name}" style="width:100%"/>
</h:column>
<h:column>
<h:commandButton actionListener=#{myBean.updateRow} onsuccess="editCardDialog.show()" >
<f:param name="carId" value=#{car.id} />
<f:param name="carName" value=#{car.name} />
</h:commandButton>
</h:column>
...
</p:dataTable>
So my Question is this, currently the only way I have gotten this to work is to in my backing bean create dummy temp global variables to set the params to so when my dialog opens it can reference the values like this
//myBean.java
private String tempCarId;
private String tempCarName;
public void setTempCarId(String tempCarId) {
this.tempCarId = carId;
}
public String getTempCarId() {
return tempCarId;
}
public void setTempCarName(String tempCarName) {
this.tempCarName = carName;
}
public String getTempCarName() {
return tempCarName;
}
public void updateRow(ActionEvent event) {
String carId = FaceContext...getParameterMap("carId");
String carName = FacesContext...getParameterMap("carName");
setTempCarId(carId);
setTempCarName(carName);
}
Then in the dialog I will just reference those temp variables
<p:dialog>
<h:inputText value=#{myBean.tempCarId} />
<h:inputText value=#{myBean.tempCarName} />
</p:dialog>
I am not sure if this is the correct way of doing it. My gut is telling me its not because it seems extremely redundant to have to create temp variables in my Bean just so I can pass them to the dialog. Does anyone know of a better more concise way of doing this so I dont have to create a million temporary variables in my backing bean?
Just replace the outputTexts in dialog below with inputTexts;
http://www.primefaces.org/showcase/ui/datatableRowSelectionByColumn.jsf
or
http://www.primefaces.org/showcase/ui/datatableRowSelectionInstant.jsf

Resources