Disable selection in a PrimeFaces data table but show previously selected value - jsf

I want to disable the selection in a PrimeFaces v8.0 data table, but show the previously selected value.
This is my minimal example project
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html
xml:lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Disable table selection</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="1">
<p:dataTable var="value"
value="#{disabledTableSelectionBean.values}"
selection="#{disabledTableSelectionBean.selectedValue}"
disabledSelection="true"
rowKey="#{value}">
<p:column selectionMode="single" width="15" />
<p:column headerText="Value">
<h:outputText value="#{value}" />
</p:column>
</p:dataTable>
</h:panelGrid>
</h:form>
</h:body>
</html>
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import lombok.Getter;
import lombok.Setter;
#Setter
#Getter
#Named
#ViewScoped
public class DisabledTableSelectionBean implements Serializable {
private List<String> values;
private String selectedValue = "6";
#PostConstruct
public void initialize() {
values = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "10");
}
}
The displayed table looks like this
Disabled selection in PrimeFaces data table
What I want is, that the radio buttons are disabled, but to show the selected value "6", I selected in the backend bean.
Is there a way to make this work?

Your code works fine with Primefaces 6.2, with 8.0 you can try with this code:
<p:dataTable var="value" value="#{disabledTableSelectionBean.values}"
selection="#{disabledTableSelectionBean.selectedValue}"
rowKey="#{value}">
<p:column selectionMode="single" width="15"
styleClass="ui-state-disabled" />
<p:column headerText="Value">
<h:outputText value="#{value}" />
</p:column>
</p:dataTable>
Basically you remove the disable selection and add the style class directly on the radio column.

Related

View scoped JSF bean is used in multiple tabs

I have a simple example in which a JSF bean with view scope is called from different browser tabs
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</h:head>
<h:body>
<h:form>
<p:panelGrid columns="3">
<p:autoComplete value="#{testBean.item}"
dropdown="true"
completeMethod="#{testBean.completeItems}"
var="item"
itemLabel="#{item}"
itemValue="#{item}" />
<p:commandButton value="submit" update="selectedValue" />
<p:outputLabel id="selectedValue" value="Selected item: #{testBean.item}" />
</p:panelGrid>
</h:form>
</h:body>
</html>
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import org.apache.commons.lang3.StringUtils;
import lombok.Getter;
import lombok.Setter;
#Getter
#Setter
#Named
#ViewScoped
public class TestBean implements Serializable {
private String item;
private final List<String> items = Arrays
.asList("item0", "item1", "item2", "item3", "item4", "item5", "item6", "item7", "item8", "item9");
public List<String> completeItems(final String query) {
return items.stream()
.filter(i -> StringUtils.containsIgnoreCase(i, query))
.collect(Collectors.toList());
}
}
When I open the same page in a different browser tab, after selecting a value, I see the selected value from the other tab. I thought a view scoped bean would be created for each browser tab.
I am using Spring Boot v2.5.6, Glassfisch Jakarta Faces v2.3.17 and PrimeFaces v11.0.0
What I am doing wrong?

Primefaces dataTable rowEdit event doesn't seem to work

I'm investigating PrimeFaces recently. I try to create editable DataTable. I take some code from demos and created my own Facelets file and managed bean.
products.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<!-- some headers -->
</h:head>
<h:body>
<h:form>
<p:dataTable id="products" var="product" value="#{productsBean.products}" editable="true" style="margin-bottom: 20px; width: 1000px;">
<f:facet name="header">Products</f:facet>
<p:ajax event="rowEdit" listener="#{productsBean.onRowEdit}" />
<p:ajax event="rowEditCancel" listener="#{productsBean.onRowCancel}" />
<p:column headerText="Nazwa">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{product.name}" /></f:facet>
<f:facet name="input"><p:inputText value="#{product.name}" style="width:100%" label="Nazwa"/></f:facet>
</p:cellEditor>
</p:column>
<!-- more columns... -->
<p:column style="width:32px">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
ProductsBean.java:
import java.io.Serializable;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.event.RowEditEvent;
// more imports...
#SessionScoped #ManagedBean
public class ProductsBean implements Serializable {
private static final long serialVersionUID = -501520863695260180L;
#EJB
private ProductDao productDao;
#EJB
private UnitDao unitDao;
private List<Product> products;
private List<Unit> units;
#PostConstruct
private void init() {
products = productDao.findAll();
units = unitDao.findAll();
}
public void onRowEdit(RowEditEvent event) {
System.out.println("onRowEdit");
}
public void onRowCancel(RowEditEvent event) {
System.out.println("onRowCancel");
}
public List<Product> getProducts() {
return products;
}
public List<Unit> getUnits() {
return units;
}
}
Unfortunatelly, onRowEdit(RowEditEvent) is never invoked, only my table gets red. I don't get any other feedback. onRowCancel(RowEditEvent) is invoked correctly. What am I doing wrong or what I am missing? Thanks for your help.

PrimeFaces "tabChange" event with dynamic number of tabs

I need to get title of currently active tab inside my TabView. TabView is constructed with dynamic number of tabs with listener attached to "tabChanged":
<p:tabView value="#{bean.list}" var="listItem">
<p:ajax event="tabChange" listener="#{listenerBean.onChange}" />
<p:tab title="#{listItem.stringProperty}">
</p:tab>
</p:tabView>
The problem is that TabChangeEvent object received by onChange(TabChangeEvent event) always contains first tab instead of the active one.
public void onChange(TabChangeEvent event) {
event.getTab().getTitle(); //allways returns title of first tab
}
This behavior is only true for dynamic number of tabs in TabView if I define each tab explicitly, TabChangeEvent works fine.
Any suggestions? Thanks.
I use PrimeFaces 3.5 with JSF2.1 and Servlets 2.5
The following minimal example worked for my like a charm by printing the title of the tab to activate every time I click on it:
page.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<f:view>
<h:head/>
<h:body>
<h:form>
<p:tabView value="#{bean.items}"
var="item">
<p:ajax event="tabChange"
listener="#{bean.printTitle}"
update="#form"/>
<p:tab title="#{item}">
</p:tab>
</p:tabView>
</h:form>
</h:body>
</f:view>
</html>
Bean.java
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import org.primefaces.event.TabChangeEvent;
#Named
#ViewScoped
public class Bean implements Serializable {
private final List<String> items = Arrays.asList("Hello", "This", "Is", "TabView");
public List<String> getItems() {
return items;
}
public void printTitle(TabChangeEvent event) {
System.out.println("title = [" + event.getTab().getTitle() + "]");
}
}

Primefaces: global message not showing in dialog on first access

i am trying to show a globalMessage in the main form as well as within a dialog. The message within the dialog only shows when the dialog is opened a second time.
I can't get it to work. Can anyone solve this problem? I'd really appreciate it!
I am using JSF Mojarra 2.2.1, Primefaces 4.0 and Apache Tomcat 7.0.
Here is my view (testView.xhtml):
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<h:body>
<h:form id="testForm">
<p:messages globalOnly="true" showDetail="true" closable="true" />
<p:commandButton value="ClickMe" action="#{testBean.displayMessage()}"
update="testForm :testDialogForm" oncomplete="PF('testDialog').show()" />
</h:form>
<p:dialog id="testDialogId" widgetVar="testDialog"
dynamic="true" closable="true" closeOnEscape="true"
header="Dialog with message">
<h:form id="testDialogForm">
<p:messages globalOnly="true" showDetail="true" closable="true" />
<h:outputText value="This outputText should not be alone." />
</h:form>
</p:dialog>
</h:body>
Here is my bean (TestBean.java):
package de.simply.local.tbx.webbeans;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean(name = "testBean")
#ViewScoped
public class TestBean {
public void displayMessage() {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"This is the summary.", "These are the details."));
}
}

Datatable items set to null upon commandLink action

If I run the app and click the first p:commandLink, the item gets set as expected. When clicking another p:commandLink the previous one will be removed (null). The h:commandLink does not have that problem.
If I add :theform:output to the update parameter of the p:commandLink, the previously clicked item stops disappearing.
What is the reason for this behaviour?
Env
Java 1.7.45
Netbeans 7.4
JSF Mojarra 2.2.4
Primefaces 4.0
Index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form id="theform">
<h:panelGroup layout="block" styleClass="tableBorder" id="tableWrapper">
<h:dataTable value="#{xtestListBean.list}" var="item">
<h:column>
<h:outputText value="#" styleClass="tableItem" />
</h:column>
<h:column>
<h:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}">
<f:ajax render=":theform:tableWrapper" />
</h:commandLink>
<p:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}"
update=":theform:tableWrapper">
</p:commandLink>
</h:column>
</h:dataTable>
</h:panelGroup>
<h:inputText value="#{xtestEntityBean.item.name}" size="40" id="output" />
</h:form>
</h:body>
</html>
XtestListBean.java
package beans;
import dto.Item;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class XtestListBean implements Serializable {
private List<Item> list;
public XtestListBean() {
list = new ArrayList();
list.add(new Item("Test 1"));
list.add(new Item("Test 2"));
list.add(new Item("Test 3"));
list.add(new Item("Test 4"));
list.add(new Item("Test 5"));
list.add(new Item("Test 6"));
list.add(new Item("Test 7"));
}
public List<Item> getList() {
return list;
}
}
XtestEntityBean.java
package beans;
import dto.Item;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class XtestEntityBean implements Serializable {
private Item item = new Item();
public XtestEntityBean() {
}
public void setItem(Item item) {
this.item = item;
}
public Item getItem() {
return item;
}
public String getVersion() {
return FacesContext.class.getPackage().getImplementationTitle()
+ " version "
+ FacesContext.class.getPackage().getImplementationVersion();
}
}
That only looks like so. It's just that the <h:inputText value="#{xtestEntityBean.item.name}"> is also processed when the <p:commandLink> is invoked. In effects, the item's name is submitted with an empty/null value and that get reflected in the table. It's not the whole Item instance which became null or so.
How is this caused? Well, the <f:ajax execute> defaults to #this, meaning that only the current component (i.e. the command link) is processed during the form submit. However, the PrimeFaces equivalent, <p:commandLink process> defaults to #form, meaning that the entire parent form is processed during form submit, including that empty input field referring the item name.
If you explicitly set <p:commandLink process> to #this, the same as <f:ajax execute>'s default, then it should work as intented.
<p:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}"
process="#this" update=":theform:tableWrapper">
</p:commandLink>

Resources