jsf datatable with selectbooleancheckbox - jsf

I have following code:
JSF PAGE
<h:dataTablevalue="#{bean.records}" var="app">
<h:column>
<h:selectBooleanCheckbox value="#{bean.checked[app.id]}"/>
<f:facet name="footer">
<h:commandButton value="submit" action="#{bean.submitPublic}"/>
</f:facet>
</h:column>
and BEAN code:
#SessionScoped
public class bean
private Map<Long, Boolean> checked = new HashMap<Long, Boolean>();
private List<Application> checkedItems = new ArrayList<Application>();
public void submit() {
for (Application app : getRecords()) {
if (checked.get(app.getId())) {
checkedItems.add(app);
}
}
checked.clear();
//here logic for selected apps
}
public Map<Long, Boolean> getChecked() {
return checked;
}
public void setChecked(Map<Long, Boolean> checked) {
this.checked = checked;
}
problem is when I click button, selected values are not submitted.
I was reading this article:
How to use <h:selectBooleanCheckbox> in <h:dataTable> to select multiple rows?
did everything the same way, but it does not work.

Update the datatable when the Checkbox is selected.
<h:selectBooleanCheckbox value="#{bean.checked[app.id]}">
<f:ajax event="valueChange" render=":YOUR_FORM_ID:YOUR_TABLE_ID"/>
</h:selectBooleanCheckbox>

Related

How to check another checkbox when click first checkbox? My checkbox list retrieve from datafile

I am new in jsf. My checkbox list retrieve from datatable. if checkbox with documentId 101 selected, system should auto select another checkbox which documentId 102. How to code this problem?
<p:dataTable id="popup1" var="comp1" rows="10"
value="#{ExaBackingBean.managedBean.popupcomp1List}"
editable="true"
selection="#{ExaBackingBean.managedBean.popupcomp1Select}"
rowKey="#{comp1.documentId}" rowIndexVar="index">
<ac:paginator for="popup1"></ac:paginator>
<p:column style="width:3px;text-align:center;" >
<p:selectBooleanCheckbox value="#{comp1.selected}">
<p:ajax listener="#{ExaBackingBean.ckechboxSelectPairingAction(comp1.documentId)}" partialSubmit="true" process="#this" update="#([id$=CompChecklist])" />
</p:selectBooleanCheckbox>
</p:column>
// ExaBackingBean
public void ckechboxSelectPairingAction(int documentId) throws Exception {
if (documentId == 101) {
System.out.println("documentId test"+documentId);
--- checkbox101 & checkbox102 will check
}
First of all, you want to show many check boxes, then you should to use selectManyCheckbox instead of selectBooleanCheckbox.
Let's create pseudo example, how to choose some value depending other:
HTML clode
<p:selectManyCheckbox id="basic" value="#{bean.selectedItems}">
<f:selectItems value="#{bean.availableItems}" />
<p:ajax listener="#{bean.someLogic}" update="someComponent"/>
</p:selectManyCheckbox>
BackedBean
private Map<String, String> availableItems; // +getter (no setter necessary)
private List<String> selectedItems; // +getter +setter
#PostConstruct
public void init() {
availableItems = new LinkedHashMap<String, String>();
availableItems.put("Document1 label", "document1");
availableItems.put("Document2 label", "document2");
availableItems.put("Document3 label", "document3");
}
public void someLogic() {
boolean contains = selectedItems.contains("document1");
if (contains) {
selectedItems.add("document2");
}
}

Lazy loading in p:dataTable / p:dataGrid and f:setPropertyActionListener

I have a <p:dataTable> as follows.
<p:dataTable var="row" value="#{testManagedBean.list}">
<p:column>
<h:outputText value="#{row.subCatId}"/>
</p:column>
<p:column>
<p:commandLink process="#this">
<h:outputText value="#{row.subCatName}"/>
<f:setPropertyActionListener target="#{testManagedBean.subCatName}" value="#{row.subCatName}"/>
</p:commandLink>
</p:column>
</p:dataTable>
The corresponding RequestScoped managed bean is as follows.
#ManagedBean
#RequestScoped
public final class TestManagedBean
{
#EJB
private final TestBeanLocal testService=null;
private List<SubCategory>list;
private String subCatName;
#PostConstruct
private void init()
{
list=testService.getSubCategoryList();
}
public List<SubCategory> getList() {
return list;
}
public String getSubCatName() {
return subCatName;
}
public void setSubCatName(String subCatName) {
System.out.println("setSubCatName() called : "+subCatName);
this.subCatName = subCatName;
}
}
When <p:commandLink> inside <p:dataTable> is clicked, the corresponding setter method associated with <f:setProperyActionListener> (setSubCatName()) is called and the value is correctly set to the target property which is subCatName in this managed bean.
I have avoided many things like paging to have a minimal example.
Now, I need to populate this <p:dataTable> lazily. I'm changing this <p:dataTable> and the corresponding managed bean as follows.
<p:dataTable var="row" value="#{testManagedBean}" lazy="true" rows="10" rowIndexVar="rowIndex">
<p:column>
<h:outputText value="#{row.subCatId}"/>
</p:column>
<p:column>
<p:commandLink process="#this">
<h:outputText value="#{row.subCatName}"/>
<f:setPropertyActionListener target="#{testManagedBean.subCatName}" value="#{row.subCatName}"/>
</p:commandLink>
</p:column>
</p:dataTable>
And the associated JSF managed is given below.
#ManagedBean
#RequestScoped
public final class TestManagedBean extends LazyDataModel<SubCategory> implements Serializable
{
#EJB
private final TestBeanLocal testService=null;
private String subCatName;
private static final long serialVersionUID = 1L;
public String getSubCatName() {
return subCatName;
}
public void setSubCatName(String subCatName) {
System.out.println("setSubCatName() called : "+subCatName);
this.subCatName = subCatName;
}
#Override
public List<SubCategory> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, String> filters)
{
setRowCount(4); //Just an example. Otherwise, fetch from the database.
return testService.getSubCategoryList(first, pageSize, sortField, sortOrder, filters);
}
}
Now, when <p:commandLink> inside <p:dataTable> is clicked, the corresponding setter method associated with <f:setProperyActionListener> (setSubCatName()) is not invoked.
The setSubCatName() is only invoked, when the managed bean is decorated with a broader scope like #ViewScoped (in case of lazy is set to true)
Why doesn't <f:setPropertyActionListener> work with a request scoped managed managed bean, when a <p:dataTable> (also true for <p:dataGrid>) is lazily loaded?
Is it mandatory to designate a managed bean with a broader than a request scope in such cases?
yes it is mandatory because the underlying model has to be the same instance. even if it has the same values it won't work.
like you, i've met this behavior: primefaces datatable lazy loading and commandbutton per row

p:selectOneMenu value still required

In my xhtml page i have two dependant selectOneMenu, with the second one being filled in an ajax call. Here's the jsf code fragment:
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="Dirección:" for="direccion"/>
<p:inputText id="direccion" value="#{datosInstitucion.institucion.direccion}" required="true" label="Dirección"/>
<h:outputLabel value="Departamento:" for="departamento"/>
<p:selectOneMenu id="departamento" value="#{datosInstitucion.idDepartamento}" required="true" label="Departamento">
<f:selectItem itemLabel="Seleccione el departamento" itemValue="#{null}"/>
<c:forEach items="#{datosInstitucion.departamentos}" var="departamento">
<f:selectItem itemLabel="#{departamento.nombre}" itemValue="#{departamento.id}"/>
</c:forEach>
<f:ajax render="municipio" listener="#{datosInstitucion.cargarMunicipios()}"/>
</p:selectOneMenu>
<h:outputLabel value="Municipio:" for="municipio"/>
<p:selectOneMenu id="municipio" value="#{datosInstitucion.idMunicipio}" required="true" label="Municipio">
<f:selectItem itemLabel="Seleccione el municipio" itemValue="#{null}"/>
<c:forEach items="#{datosInstitucion.municipios}" var="municipio">
<f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
</c:forEach>
</p:selectOneMenu>
</h:panelGrid>
This fragment of code is inside a primefaces wizard component, so when the 'next' button is pressed a validation error is caused for the second selectOneMenu even when there's a value set.
What could be causing this behavior?
Relevant backing bean code:
#ManagedBean(name = "datosInstitucion")
#ViewScoped
public class DatosInstitucion implements Serializable{
#EJB
private Instituciones instituciones;
#EJB
private Parametros parametros;
#Inject
private Mensajes mensajes;
private List<Departamento> departamentos;
private List<Municipio> municipios;
private Map<Integer, Departamento> mapaDepartamentos;
private Integer idDepartamento;
private Integer idMunicipio;
private Institucion institucion;
#PostConstruct
private void inicializar(){
this.mapaDepartamentos = new HashMap<>();
this.departamentos = parametros.consultarDepartamentos();
for(Departamento departamento : departamentos){
this.mapaDepartamentos.put(departamento.getId(), departamento);
}
this.prepararInstitucion();
}
private void prepararInstitucion(){
this.institucion = new Institucion();
this.institucion.setResponsable(new Persona());
}
public Institucion getInstitucion() {
return institucion;
}
public List<Departamento> getDepartamentos(){
return departamentos;
}
public TipoIdentificacion[] getTiposIdentificacion(){
return TipoIdentificacion.deResponsables();
}
public Integer getIdDepartamento() {
return idDepartamento;
}
public void setIdDepartamento(Integer idDepartamento) {
this.idDepartamento = idDepartamento;
}
public Integer getIdMunicipio() {
return idMunicipio;
}
public void setIdMunicipio(Integer idMunicipio) {
this.idMunicipio = idMunicipio;
}
public void cargarMunicipios(){
idMunicipio = null;
if(idDepartamento != null){
this.municipios = mapaDepartamentos.get(idDepartamento).getMunicipios();
}else{
this.municipios = Collections.emptyList();
}
}
public List<Municipio> getMunicipios() {
return municipios;
}
public void confirmar(){
this.instituciones.guardar(institucion);
this.mensajes.exito("La institución ha sido registrada en el sistema");
this.prepararInstitucion();
}
}
This is because you are using JSTL <c:foreach> with JSF. The life cycle of JSTL vs JSF matters. JSTL is executed when the view is being built, while JSF is executed when the view is being rendered. The two do not work in synch with each other. In your case, you need to use <f:selectItems> instead of <c:foreach>
Replace:
<c:forEach items="#{datosInstitucion.municipios}" var="municipio">
<f:selectItem itemLabel="#{municipio.nombre}" itemValue="#{municipio.id}"/>
</c:forEach>
with:
<f:selectItems value="#{datosInstitucion.municipios}"
var="municipio" itemLabel="#{municipio.nombre}"
itemValue="#{municipio.id}"/>
For more reading, I suggest you to read the following answer

How to get dynamically rendered <h:inputText> value in back end in JSF

I am able to render dynamic but don't know how to get those dynamically created values in back end.
test.xhtml
<h:form>
Insert Your Desire Number : <h:inputText value="#{bean.number}">
<f:ajax listener="#{bean.submitAjax}" execute="#form" render="#form" event="keyup" />
</h:inputText>
<br></br>
<h:outputText value="#{bean.text}" />
<h:dataTable value="#{bean.items}" var="item">
<h:column>
<h:inputText value="#{item.value}" />
</h:column>
</h:dataTable>
<h:commandButton value="Submit" action="#{item.submit}" />
</h:form>
If I render 3 input boxes, and when I submit the button i get the last value only, Can someone guide me how can i
Bean.java
#ManagedBean(name="bean")
#SessionScoped
public class Bean {
private int number;
private List<Item> items;
private Item item;
//getter and setter are omitted
public void submitAjax(AjaxBehaviorEvent event)
{
items = new ArrayList<Item>();
for (int i = 0; i < number; i++) {
items.add(new Item());
}
}
}
Item.java
private String value;
//getter and setter are omitted
public void submit() {
System.out.println("Form Value : "+value);
}
Your submit() method is in the wrong place. You should put it on the managed bean, not on the entity.
Thus so,
<h:commandButton value="Submit" action="#{bean.submit}" />
with
public void submit() {
for (Item item : items) {
System.out.println(item.getValue());
}
}
or more formally,
#EJB
private ItemService service;
public void submit() {
service.save(items);
}

How to implement "Select all" on selectManyCheckbox

I want to set checkboxes of a selectManyCheckbox to checked if a condition is true "#{myBean.isCondition}":
MyBean.java
public class MyBean{
private boolean isCondition;
...
public boolean isCondition{
return isCondition;
}
...
}
my_page.jspx :
<h:selectManyCheckbox
layout="pageDirection"
label="#{messages['numsTelephone.label']}"
value="#{listSelected}">
<s:selectItems var="clientTelephone"
value="#{list}"
label="#{clientTelephone}" />
</h:selectManyCheckbox>
I need to know if it exist something like
checked = "#{myBean.isCondition}"
that I can add in my selectManyCheckbox bloc ? Or should I use a javascript ?
Any other solution is welcome too.
My other question is how to set myBean.isCondition to true if a checkbox is selected ?
Thanks,
Use <f:ajax> in the "Select all" checkbox and do the selection job in the listener method and then re-render the checkboxes.
Kickoff example:
<h:form>
<h:selectBooleanCheckbox value="#{bean.selectAll}">
<f:ajax listener="#{bean.onSelectAll}" render="items" />
</h:selectBooleanCheckbox>
<h:selectManyCheckbox id="items" value="#{bean.selectedItems}">
<f:selectItems value="#{bean.availableItems}" />
</h:selectManyCheckbox>
</h:form>
#Named
#ViewScoped
public class Bean implements Serializable {
private boolean selectAll; // +getter +setter
private List<String> selectedItems; // +getter +setter
private Map<String, String> availableItems; // +getter (no setter necessary)
#PostConstruct
public void init() {
availableItems = new LinkedHashMap<String, String>();
availableItems.put("Foo label", "foo");
availableItems.put("Bar label", "bar");
availableItems.put("Baz label", "baz");
}
public void onSelectAll() {
selectedItems = selectAll ? new ArrayList<>(availableItems.values()) : null;
}
// ...
}

Resources