While the view can get all values from the bean, when a checkbox (h:selectBooleanCheckbox) is toggled the bean is not updated. The setSelected() method in Item is never called from the view.
I've tried changing the scope of the bean to application, using a map instead of a value for the selected property and a foolish attempt at writing my own ajax javascript function.
The application I'm working with is a bit legacy so I'm using Tomcat 6, JSF 1.2 and Richfaces 3.3.3.Final.
It seems like it should be simple, I think I'm missing something obvious, but I've been at this for two days and can't figure out why the bean isn't updated.
My view is:
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<head>
<title>JSF</title>
</head>
<body>
<h:form id="tableForm">
<rich:dataTable id="table" value="#{managedBean}" var="item" width="100%">
<rich:column label="Select" align="center" width="40px" >
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<h:selectBooleanCheckbox value="#{item.selected}" >
<a4j:support execute="#this" event="onclick" ajaxSingle="true"/>
</h:selectBooleanCheckbox>
</rich:column>
<rich:column label="Name" align="center" width="40px">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{item.name}" />
</rich:column>
</rich:dataTable>
</h:form>
</body>
</html>
I have a managed bean ItemBean in session scope:
import org.richfaces.model.ExtendedTableDataModel;
public class ItemBean extends ExtendedTableDataModel<Item>{
public ItemBean() {super(new ItemProvider());}
}
ItemProvider is:
import org.richfaces.model.DataProvider;
public class ItemProvider implements DataProvider<Item>{
private List<Item> items = new ArrayList<Item>();
public ItemProvider(){
for(int i = 0; i < 10; i++){
items.add(new Item(i, "Item "+i));
}
}
public Item getItemByKey(Object key) {return items.get((Integer)key);}
public List<Item> getItemsByRange(int fromIndex, int toIndex) {
return new ArrayList<Item>(items.subList(fromIndex, toIndex));
}
public Object getKey(Item arg0) {return arg0.getId();}
public int getRowCount() {return items.size();}
}
and Items are:
public class Item {
private final int id;
private final String name;
private boolean selected;
public Item(int id, String name) {
this.id = id;
this.name = name;
selected = false;
}
public int getId(){
return id;
}
public String getName(){
return name;
}
public boolean isSelected(){
return selected;
}
public void setSelected(boolean selected){
this.selected = selected;
}
}
I would assume, that your vanilla html, head and body tags might cause this.
Ajax-stuff (javascript) sometimes has to go into the <head> section of the page (along with required script references). Because JSF is working with components, it needs to insert the javascript required for a certain component at the time the component is added to the underlaying Object-Model.
Therefore JSF itself needs to manage the html, head and body tags.
So, instead of creating them as vanilla-html, use the proper<h:html>, <h:body> and <h:head> tags, which will handover this task to JSF. This way, the required javascript code for your onclick-event handler should be generated and the checkbox should work as expected.
The issue was that I hadn't set up my web.xml properly.
I was missing the following which routes the request to richfaces:
<filter>
<display-name>RichFaces Filter</display-name>
<filter-name>richfaces</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>richfaces</filter-name>
<servlet-name>Faces Servlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
Related
How can I fix the following error? The start language is German. If I select english it stays with the german text. However, if I then select German, I get English and if I then select English, I get German language. However, when the English text appears instead of the German text, "de" is displayed correctly next to language (Language de:) in the index.xhtml. To show which language is selected I use #{language.localeCode} in the index.xhtml. I use Apache MyFaces 2.3-next-M6 with Quarkus. What am I doing wrong?
index.xhtml
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html" encoding="UTF-8" locale="#{language.localeCode}">
<f:loadBundle basename="messages" var="msg" />
<h:head>
<h:outputStylesheet name="primeflex/primeflex.css" />
</h:head>
<h:body>
<p:growl>
<p:autoUpdate />
</p:growl>
<h:form id="formlanguagechanger">
<h:panelGrid columns="2">
Language #{language.localeCode}:
<h:selectOneMenu value="#{language.localeCode}" onchange="submit()"
valueChangeListener="#{language.countryLocaleCodeChanged}">
<f:selectItems value="#{language.countriesInMap}" />
</h:selectOneMenu>
</h:panelGrid>
</h:form>
<h:outputText value="#{msg.title}" />
</h:body>
</f:view>
</html>
LanguageBean.java
#Named("language")
#SessionScoped
public class LanguageBean implements Serializable {
private static final long serialVersionUID = 1L;
private String localeCode;
#PostConstruct
public void init() {
localeCode = "de";
}
private static Map<String, Locale> countries;
static {
countries = new LinkedHashMap<String, Locale>();
countries.put("Deutsch", new Locale("de"));
countries.put("English", new Locale("en"));
}
public Map<String, Locale> getCountriesInMap() {
return countries;
}
public String getLocaleCode() {
return localeCode;
}
public void setLocaleCode(String localeCode) {
this.localeCode = localeCode;
}
// value change event listener
public void countryLocaleCodeChanged(ValueChangeEvent e) {
String newLocaleValue = e.getNewValue().toString();
// loop country map to compare the locale code
for (Map.Entry<String, Locale> entry : countries.entrySet()) {
if (entry.getValue().toString().equals(newLocaleValue)) {
FacesContext.getCurrentInstance().getViewRoot().setLocale((Locale) entry.getValue());
}
}
}
}
This code works fine for me in Mojarra 2.3.17.
In Myfaces 2.3.9, however, I could reproduce the described issue.
The root cause is that the <f:loadBundle> is not (re)initialized during view render time but during view build time only. This might be a bug in MyFaces.
I could work around the issue by replacing the <f:loadBundle> tag by this entry in faces-config.xml.
<application>
...
<resource-bundle>
<base-name>messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
It's at least not a Quarkus related problem. So I've fixed your question.
See also:
Localization in JSF, how to remember selected locale per session instead of per request/view
I need to display a message when LazyDataModel load method loads the data. I am using primefaces growl to display the message and updating it from load method using the below code, but It is not working (not seeing any message on UI). Please suggest what I am doing wrong, It seems something related to the asynchronous behaviour of load method but I am not sure how to fix it.
JSF Bean -
#ManagedBean(name = "cData")
#ViewScoped
public class DataPage implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2193735279937686495L;
#PostConstruct
public void init() {
FacesContext.getCurrentInstance().addMessage("growl-sticky", new
FacesMessage(FacesMessage.SEVERITY_INFO, "Sticky Message",
"Message Content from init"));
loadData();
}
private void loadData() {
FacesContext.getCurrentInstance().addMessage("growl-sticky", new
FacesMessage(FacesMessage.SEVERITY_INFO, "Sticky Message",
"Message loadData before load"));
setMobiles(new LazyDataModel<Mobile>() {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public List<Mobile> load(int first, int pageSize,
String sortField, SortOrder sortOrder,
Map<String, Object> filters) {
List<Mobile> data = new DataRepo().getMobileData();
mobiles.setRowCount(data.size());
FacesContext.getCurrentInstance().addMessage("growl-sticky", new
FacesMessage(FacesMessage.SEVERITY_INFO, "Sticky Message",
"Message Content from load"));
return data;
}
#Override
public Mobile getRowData(String rowKey) {
// some code
}
#Override
public Object getRowKey(Mobile object) {
// some code
}
});
}
public LazyDataModel<Mobile> getMobiles() {
return mobiles;
}
public void setMobiles(LazyDataModel<Mobile> mobiles) {
this.mobiles = mobiles;
}
private LazyDataModel<Mobile> mobiles = null;
}
xhtml page -
<?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://java.sun.com/jsf/html"
xmlns:c = "http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>DataTable tag Example</title>
</h:head>
<h:body>
<h3>Mobile Details</h3>
<h:form>
<c:metadata>
<c:viewAction action="#{cData.showSticky}" />
</c:metadata>
<p:growl id="growl-sticky" showDetail="true" sticky="true" autoUpdate="true"/>
<p:commandButton actionListener="#{cData.showSticky}"
update="growl-sticky" value="Info" style="width: 10rem"
styleClass="ui-button-help" />
<h:dataTable value="#{cData.mobiles}" var="mobile" border="2" paginator="true" rows="10"
lazy="true">
<h:column>
<c:facet name="header">Name</c:facet>
#{mobile.companyname}
</h:column>
<h:column>
<c:facet name="header">Model Number</c:facet>
#{mobile.modelnumber}
</h:column>
<h:column>
<c:facet name="header">Color</c:facet>
#{mobile.color}
</h:column>
<h:column>
<c:facet name="header">Quantity</c:facet>
#{mobile.quantity}
</h:column>
<h:column>
<c:facet name="header">Price</c:facet>
#{mobile.price}
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
The issue why your message doesn't show up is because of the phase when Load is called. Explanation and workaround below.
The load method is invoked in RENDER_RESPONSE phase, which is inconvenient because error messages could occur here and they would not typically be rendered because p:messages are in most cases rendered as one of first components.
Issue: https://github.com/primefaces/primefaces/issues/3501
Workaround: https://github.com/primefaces/primefaces/issues/3501#issuecomment-469731529
I've one table embedded into another table. My problem: How to render only the inner table when a row was removed?
Bean:
#Named
#ViewScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = -5633666299306108430L;
private List<String> strLst1;
private List<String> strLst2;
#PostConstruct
public void init() {
strLst1 = Arrays.asList("a", "b", "c");
strLst2 = Arrays.asList("d", "e", "f");
}
public List<String> getStrLst1() {
return strLst1;
}
public List<String> getStrLst2() {
return strLst2;
}
public void removeFromStrLst2(String val) {
strLst2.remove(val);
}
}
Facelet:
<!DOCTYPE html>
<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<h:dataTable
id="outerTable"
var="str1"
value="#{testBean.strLst1}"
border="1">
<h:column>
<h:panelGroup id="innerTableContainer">
<h:dataTable
id="innerTable"
var="str2"
value="#{testBean.strLst2}"
border="1">
<h:column>
<h:outputText value="#{str1}: #{str2}" />
</h:column>
<h:column>
<h:commandButton
id="removeButton"
action="#{testBean.removeFromStrLst2(str2)}"
value="RemoveFromStrLst2">
<f:ajax render="innerTableContainer" /> <!-- Problem location -->
</h:commandButton>
</h:column>
</h:dataTable>
</h:panelGroup>
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
My problem is the Ajax-render attribute which doesn't get the correct id (examples for the first row):
innerTableContainer leads to mojarra.ab(this,event,'action',0,'innerTableContainer') It doesn't work!
innerTable leads to mojarra.ab(this,event,'action',0,'form:outerTable:0:innerTable:0') It doesn't work!
#parent leads to mojarra.ab(this,event,'action',0,'form:outerTable:0:innerTable:0:j_idt14') It doesn't work!
#namingcontainer leads to mojarra.ab(this,event,'action',0,'form:outerTable:0:innerTable:0') It doesn't work!
#form works but this isn't I was looking for.
The correct and working id would be form:outerTable:0:innerTableContainer but how to get it?
Mojarra 2.3.9.SP01
I am developing a project using JSF. In an opening popup window, i want to show some details about a product but can not get view scoped bean' s value on a datatable.
Can you help me?
Thanks.
Here is my UrunuDenetlemeSayfasi.xhtml code snippet:
<h:commandLink onclick="window.open('UruneGozAt.xhtml',
'Ürün İçeriği', config='width=700, height=400, top=100, left=100,
scrollbars=no, resizable=no');"
action="#{uruneGozAtBean.urunIdsineGoreUrunIcerigiGetir}" value="Ürün İçeriğine Göz At">
<f:param name="urunid" value="#{urun.urunID}" />
</h:commandLink>
Here is UrunuGozAt.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
Here is UruneGozAtBean.java
UrunDenetlemeSayfasiBean urunDenetle = new UrunDenetlemeSayfasiBean();
UrunDenetleService urunService = new UrunDenetleService();
private UrunIcerik urunIcerik = new UrunIcerik();
private Long urunIdParametre;
public UrunIcerik getUrunIcerik() {
return urunIcerik;
}
public void setUrunIcerik(UrunIcerik urunIcerik) {
this.urunIcerik = urunIcerik;
}
public Long getUrunIdParametre() {
return urunIdParametre;
}
public void setUrunIdParametre(Long urunIdParametre) {
this.urunIdParametre = urunIdParametre;
}
public void urunIdsineGoreUrunIcerigiGetir() {
setUrunIcerik(urunService.urunIdsineGoreUrunIcerigiGetir(urunIdEldeEt()));
}
public Long urunIdEldeEt(){
FacesContext fc = FacesContext.getCurrentInstance();
setUrunIdParametre(getUrunIdParametre(fc));
return getUrunIdParametre();
}
public Long getUrunIdParametre(FacesContext fc){
Map<String, String> parametre = fc.getExternalContext().getRequestParameterMap();
return Long.valueOf(parametre.get("urunid")).longValue();
}
EDIT:
This is now my current implementation, it returns null.
i am developing a project using JSF. In an opening popup window, i want to show some details about a product but can not get view scoped bean' s value on a datatable.
Can you help me?
Thanks.
Here is my UrunuDenetlemeSayfasi.xhtml code snippet:
<h:commandLink onclick="window.open('UruneGozAt.xhtml','Ürün İçeriği',
config='width=700, height=400, top=100, left=100, scrollbars=no, resizable=no');"
value="Ürün İçeriğine Göz At"> <f:param name="urunId" value="#{urun.urunID}" />
</h:commandLink>
Here is UruneGozAt.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:metadata>
<f:viewParam name="urunId" value="#{uruneGozAtBean.urunId}"
required="false" />
<f:viewAction action="#{uruneGozAtBean.urunIdsineGoreUrunIcerigiGetir()}" />
</f:metadata>
<h:head>
<title>Ürün İçeriği</title>
<!-- add this always, even if it's empty -->
</h:head>
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
Here is UruneGozAtBean.java
#ManagedBean
#ViewScoped
public class UruneGozAtBean {
public UrunDenetlemeSayfasiBean urunDenetle = new UrunDenetlemeSayfasiBean();
public UrunDenetleService urunService = new UrunDenetleService();
private ArrayList<UrunIcerik> urunIcerik = new ArrayList<UrunIcerik>();
private Long urunId;
public Long getUrunId() {
return urunId;
}
public void setUrunId(Long urunId) {
this.urunId = urunId;
}
public ArrayList<UrunIcerik> getUrunIcerik() {
return urunIcerik;
}
public void setUrunIcerik(ArrayList<UrunIcerik> urunIcerik) {
this.urunIcerik = urunIcerik;
}
public void urunIdsineGoreUrunIcerigiGetir() {
setUrunIcerik(urunService.urunIdsineGoreUrunIcerigiGetir(urunIdEldeEt()));
System.out.print("aaa");
}
public Long urunIdEldeEt() {
FacesContext fc = FacesContext.getCurrentInstance();
setUrunId(getUrunId(fc));
return getUrunId();
}
public Long getUrunId(FacesContext fc) {
Map<String, String> parametre = fc.getExternalContext().getRequestParameterMap();
return Long.valueOf(parametre.get("urunId")).longValue();
}
}
#ViewScoped beans are alive per view. If you open a popup window from your current view, then you're opening a new view, so even if it uses the same managed bean to display the data, since they're different views, they use different instances of the same class.
In cases like this, you should pass a parameter through query string, then receive it in your view and process it to load the desired data. In this case, your code would be like this (note: make sure you send the parameter with name "urunId"):
UrunuGozAt.xhtml:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<!-- add this always, even if it's empty -->
<f:metadata>
<f:viewParam name="urunId" value="#{uruneGozAtBean.urunId}"
required="false" />
<f:viewAction action="#{uruneGozAtBean.loadData}" />
</f:metadata>
</h:head>
<h:body>
<h:dataTable class="table table-striped"
value="#{uruneGozAtBean.urunIcerik}" var="urun">
<h:column>
<f:facet name="header">
<h:outputText value="barkod no" />
</f:facet>
<h:outputText value="#{urun.barkodNo}" />
</h:column>
</h:dataTable>
</h:body>
</html>
UruneGozAtBean managed bean:
#ViewScoped
#ManagedBean
public class UruneGozAtBean {
//your current fields, getters and setters...
private Long urunId;
//getter and setter for this field...
public void loadData() {
if (urunId != null) {
//load the data for the table...
}
}
}
More info:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
DataTable expects a list to iterate through, but as far as I can see you return an UrunIcerik object.
I am not able to get he the selected value from the table withe bean in View scope.
Following code doesn't work but it works when I uses Session or Request scope.
Here's my JSF page:
<!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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<f:view>
<h:head>
<title>Sample JSF/Prime Page</title>
</h:head>
<h:body>
<h:form id="primeForm">
<p:panel id="toggle1" header="Panel 1" collapsed="#{prime.toggle1}" footer=" footer Info if required " toggleable="true" closable="true" >
<p:dataTable id="cars" value="#{prime.listModel}" var="data" paginator="true" style="width:500px"
selection="#{prime.selected}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{prime.onRowSelect}" />
<f:facet name="header">
Select a row to display a message
</f:facet>
<p:column headerText="Model">
#{data.number}
</p:column>
<p:column headerText="Model">
#{data.number}
</p:column>
</p:dataTable>
</p:panel>
</h:form>
</h:body>
</f:view>
</html>
Here's my bean:
#ManagedBean
#ViewScoped
public class Prime implements Serializable {
ArrayList<UIData> list = new ArrayList<UIData>();
private UIData selected;
private UIDataModel listModel;
private String testVaue;
private ArrayList<String> tmp = new ArrayList<String>();
private HashMap<String, List<String>> pagesMap = new HashMap<String, List<String>>();
private boolean toggle1 = true;
public Prime() {
for (int k = 1; k < 3; k++) {
UIData model =new UIData(""+k, ""+k);
list.add(model);
}
listModel = new UIDataModel(list);
}
public void onRowSelect(SelectEvent event) {
try{
System.out.println("Sellected Value : "+((UIData)event.getObject()).getNumber());
}catch (Exception e) {
e.printStackTrace();
}
}
// Getters and setters.
}
Add proper rowKey attribute to datatable. Primefaces must have a way to uniquely identify you row. That's why you should set a property which is unique to you dataset. Usually this is database primary key. In your case for example it coul be rowKey=#{data.number}.