I got some issue regarding Primefaces. There is a requirement that when we change language in my top panel from Engish to Arabic the entire layout should be displayed in right to left position (Like mirror image applying to all inner pages).please help me out.
i am including english version layout,top panel and controller beans.
1.layout
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Facelet Title</title>
<style type="text/css">
.ui-growl{
left:20px;
}
</style>
</h:head>
<body>
<ui:composition template="/home/template/common/commonLayout.xhtml">
<ui:define name="content">
<h:form enctype="multipart/form-data" dir="#{localeControllerBean.direction}" id="form1">
<div id="add">
<p:growl id="msgs" autoUpdate="true" display="icon" style="left:20px"></p:growl>
</div>
<p:panel header="#{msg['sponsor_detail']}">
<h:panelGrid columns="2">
<f:event listener="#{localeControllerBean.islang}" type="preRenderView" />
<p:outputLabel for="sname" value="#{msg['sponsor_name']}"
styleClass="label" />
<p:inputText id="sname" value="#{sponsorBean.sponsor_name}"
required="true" requiredMessage="#{msg['sponsor_name_msg']}"
styleClass="input">
<f:validator validatorId="sponsorValidator" />
</p:inputText>
<p:outputLabel for="sadd" value="#{msg['sponsoraddress']}:"
styleClass="label" />
<p:inputText id="sadd" value="#{sponsorBean.s_address}"
required="true" requiredMessage="#{msg['Sponsor_address_msg']}"
styleClass="input" />
<p:outputLabel for="smb" value="#{msg['sponsor_mbno']}:"
styleClass="label" />
<p:inputText id="smb" value="#{sponsorBean.s_mobile_no}"
required="true" requiredMessage="#{msg['sponsor_mbno_msg']}"
styleClass="input" />
<p:outputLabel for="ss" value="#{msg['sponsor_status']}:" styleClass="label" />
<p:inputText id="ss" value="#{sponsorBean.status}" required="true"
requiredMessage="#{msg['sponsor_mbno_msg']}" styleClass="input" />
</h:panelGrid>
<p:commandButton id="submit" value="#{msg['save']}" ajax="false"
action="#{sponsorBean.save}" style="margin-bottom:50px;"
update="msgs" />
<p:commandButton type="reset" value="#{msg['reset']}"
style="margin-bottom:50px;margin-left:30px;" ajax="false" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
2.toppanel Here i change language..
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<body>
<ui:composition>
<h:form>
<p:growl id="messages" >
<p:toolbar style="Font-size:small;">
<p:toolbarGroup align="left">
<h:outputText value="User : " style=" margin-left:15px;" />
<h:outputText value="#{loginBean.username}">
</h:outputText>
<p:commandButton value="Logout" action="#{loginBean.doLogout}" icon="ui-icon-extlink" />
</p:toolbarGroup>
<p:toolbarGroup align="right">
<p:commandButton value="#{loginBean.toggleButton}" action="#{loginBean.goHome}" icon="ui-icon-home"/>
<p:inputText id="firstname" value="#{manageEmployee.search}" dir="ltr" styleClass="input" style="margin-right:15px" />
<h:selectOneMenu
value="#{manageEmployee.searchFilter}" style="FONT-STYLE: plain; FONT-SIZE:small;margin-right:10px">
<f:selectItem itemLabel="All" itemValue="All" />
<f:selectItem itemLabel="Search by company" itemValue="company" />
<f:selectItem itemLabel="Search by sponsor" itemValue="sponsor" />
</h:selectOneMenu>
<p:commandButton id="submit" value="Search" ajax="false"
action="#{manageEmployee.searchRecords}" update="msgs" style="margin-left:10px" icon="ui-icon-search" />
<h:selectOneMenu value="#{localeBean.language}" onchange="submit()" style="margin-left:10px" >
<f:selectItem itemValue="en" itemLabel="English" />
<f:selectItem itemValue="ar" itemLabel="Arabic" />
</h:selectOneMenu>
</p:toolbarGroup>
</p:toolbar></p:growl>
</h:form>
</ui:composition>
</body>
</html>
3.Local Bean contoller:
import java.util.Locale;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSession;
#ManagedBean
#SessionScoped
public class LocaleBean {
private Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
public Locale getLocale() {
return locale;
}
public String getLanguage() {
return locale.getLanguage();
}
public void setLanguage(String language) {
locale = new Locale(language);
FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
session.setAttribute("user", locale);
// session.setAttribute("language", language);
}
public String save()
{
return "homePage";
}
}
4.Language controller:
import java.util.Locale;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.servlet.http.HttpSession;
#ManagedBean
#SessionScoped
public class LocaleControllerBean {
public static String dir="";
private String direction="";
public String getDirection() {
return direction;
}
public void setDirection(String direction) {
this.direction = direction;
}
public void islang(ComponentSystemEvent event)
{
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(true);
Locale l=(Locale) session.getAttribute("user");
if(l.toString().equals("ar"))
{
// dir="rtl";
setDirection("rtl");
}
else
{
setDirection("ltr");
// dir="ltr";
}
System.out.println("locale"+l);
facesContext.getViewRoot().setLocale(l);
}
}
The RTL support is something new in primefaces. I think it is not possible, just to have the whole page looking like a mirror image without actually recreating the page. The css itself probably will not do it, so you will need to create a separate page (or set of pages) to which you will be redirected after changing your locale.
More about RTL support in primefaces can be found here: http://code.google.com/p/primefaces/issues/detail?id=3890 and as you can see- it is component, by component, rather than global.
Related
The following is my code snippet in my abc.xhtml page :
<p:panelGrid id="pnlGrd_numOfLbl"
style="align:center; width:100%;" cellpadding="5">
<c:forEach var="i" begin="1" end="${specificationMB.numOfLbl}" >
<p:row>
<p:column width="50%">
<p:outputLabel value="Label ${i}" />
</p:column>
<p:column width="50%">
<p:inputText id="inputTxt_${i}" style="width:150px;" />
</p:column>
</p:row>
</c:forEach>
</panelGrid>
This is my panelGrid I am generating inputText dynamically depending
numOfLable. After generation say 2 will be generate user will add some
text to each inputText so my Question is How can I get value of dyanamically
generated inputbox.
Thanks.
This can easily be done with basics of JSF and primefaces. Here is full working Example:
XHTML File (I am using p:panel and ui:repeater)
<!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:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<link rel=" stylesheet" type="text/css" href="css/style.css"></link>
</h:head>
<h:body>
<h:form>
<p:panel header="Panel">
<ui:repeat var="lbl" value="#{tBean.lblClassess}">
<p:row>
<p:column width="50%">
<p:outputLabel value="#{lbl.lbl} :" />
</p:column>
<p:column width="50%">
<p:inputText value="#{lbl.value}" />
</p:column>
</p:row>
</ui:repeat>
</p:panel>
<p:commandButton actionListener="#{tBean.submit}" value="Subtmi" update="values"></p:commandButton>
<p:outputPanel id="values">
<ui:repeat var="lbl" value="#{tBean.lblClassess}">
<p:row>
<p:column width="50%">
<p:outputLabel value="#{lbl.value} :" />
</p:column>
</p:row>
</ui:repeat>
</p:outputPanel>
</h:form>
</h:body>
</f:view>
<body>
</body>
</html>
Managed Bean
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name = "tBean")
#ViewScoped
public class TestBean {
private List<LabelClass> lblClassess;
public TestBean() {
lblClassess = new ArrayList<LabelClass>();
lblClassess.add(new LabelClass("First Label", ""));
lblClassess.add(new LabelClass("Second Label", ""));
lblClassess.add(new LabelClass("Third Label", ""));
}
public void submit(ActionEvent e) {
for (LabelClass lbl : lblClassess) {
System.out.println(lbl.getValue());
}
}
public List<LabelClass> getLblClassess() {
return lblClassess;
}
public void setLblClassess(List<LabelClass> lblClassess) {
this.lblClassess = lblClassess;
}
}
Label Class
public class LabelClass {
private String lbl;
private String value;
public LabelClass(String lbl, String value) {
super();
this.lbl = lbl;
this.value = value;
}
public String getLbl() {
return lbl;
}
public void setLbl(String lbl) {
this.lbl = lbl;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Output
In order to get the values of your dynamically generated inputTexts. You may do something like this.
<input type="text" id="inputTxt_${i}" name="inputTxt_${i}" style="width:150px;" />
Then retrieve the text value by using this code in servlet
String inputText1 = request.getParameter("nameOfFirstInputText");
You can bind the value into the bean value object:
<input type="text" id="inputTxt_${i}" value="${specificationMB.getValue(i).value}" />
PROBLEM:
The PrimeFaces "p:focus" tag is not focusing.
-I.e., when the xhtml page is presented to the user, no input fields are in focus.
QUESTION:
Why not? How can I get "p:focus" to work properly in this simple app?
(NOTE: using Java 6, Mojarra v2.1.11, PrimeFaces v3.4.2)
index.jsp
<?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: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/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<title>testcal2 - index.xhtml</title>
<meta charset="utf-8" />
</h:head>
<h:body>
<h:form id="queryForm">
<f:event type="postValidate" listener="#{testBean.validate}" />
<h:panelGroup id="msgsx">
<p:messages showSummary="true"/>
</h:panelGroup>
<p:panel id="queryPanel" header="Test p:focus..." style="width:100%;">
<p:focus context="queryPanel"/>
<h:panelGroup id="msgs" style="height:1.5em; text-align: center;display:block">
<p:message id="lastName_msg" for="lastName" style="display:none;" showSummary="false"/>
<p:message id="birthDate_msg" for="birthDate" style="display:none;" showSummary="false"/>
<p:message id="startDate_msg" for="startDate" style="display:none;" showSummary="false"/>
</h:panelGroup>
<h:panelGroup id="querypanelgroup" style="display:inline-block;">
<h:panelGroup>
<h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">
<p:outputLabel style="margin-right: 5px;" value="Last Name:" for="lastName"/>
</h:panelGroup>
<h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">
<p:inputText
id="lastName"
value="#{testBean.parmMap['lastName']}"
requiredMessage="last name required"
size="95"
maxlength="95"
onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(0).show();return false;" >
</p:inputText>
</h:panelGroup>
</h:panelGroup>
<br/>
<br/>
<h:panelGroup>
<h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">
<p:outputLabel style="margin-right: 5px;" value="Birth Date:" for="birthDate"/>
</h:panelGroup>
<h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">
<p:inputText
id="birthDate"
value="#{testBean.parmMap['birthDate']}"
requiredMessage="birth date required"
converter="dpConverter"
styleClass="datePicker"
onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(1).show();$(this).mask('99/99/9999');return false;">
<p:ajax event="change" process="#this" update="#this"/>
</p:inputText>
</h:panelGroup>
</h:panelGroup>
<br/>
<br/>
<h:panelGroup>
<h:panelGroup style="text-align:right;vertical-align:middle;display:inline-block;width:150px">
<p:outputLabel style="margin-right: 5px;" value="Start Date:" for="startDate"/>
</h:panelGroup>
<h:panelGroup style="margin-left: 4px; vertical-align:middle;display:inline-block;width:250px;">
<p:inputText
id="startDate"
value="#{testBean.parmMap['startDate']}"
requiredMessage="start date required"
converter="dpConverter"
styleClass="datePicker"
onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(2).show();$(this).mask('99/99/9999');return false;">
<!-- optional to populate another field with same value...
onchange="$('...hashSymbolHere...queryForm\\:endDate').val($(this).val());">
-->
<p:ajax event="change" process="#this" update="#this"/>
</p:inputText>
</h:panelGroup>
</h:panelGroup>
<br/>
<br/>
<p:commandButton
id="submit"
value="Submit"
oncomplete="applyDatePicker();"
type="submit"
update="#form"
process="#form"
action="#{testBean.submitQuery}"
style="width:150px;"
styleClass="button"/>
<p:commandButton
value="Reset"
update="#form"
onclick="location.reload();return true;"
process="#this"
actionListener="#{testBean.reset}"
immediate="true"
ajax="false"/>
</h:panelGroup>
</p:panel>
</h:form>
<h:outputStylesheet library="styles" name="query.css" />
<h:outputScript library="primefaces" name="/jquery/jquery.js" />
<h:outputScript library="primefaces" name="/jquery/plugins/ui/jquery-ui.custom.js" />
<h:outputScript library="primefaces" name="/jquery/plugins/inputmask/maskedinput.js" />
<h:outputScript library="js" name="index.js" target="head" />
</h:body>
</f:view>
</html>
index.js
$(document).ready(function()
{
applyDatePicker();
});
function applyDatePicker(){
$('.datePicker').datepicker(
{
showOn: 'button',
buttonText: "Choose",
showButtonPanel: true,
showOptions: {direction: 'up'},
changeYear: true,
changeMonth: true,
yearRange: "c-120:c+0"
});
}
TestBean.java
package aaa.bbb.ccc.war;
import java.io.Serializable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.LinkedHashMap;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIForm;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ComponentSystemEvent;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
#Component("testBean")
#Scope("request")
public class TestBean implements Serializable
{
public TestBean()
{
parmMap = this.getParmMap();
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("parmMap", parmMap);
}
public void reset(ActionEvent event)
{
LinkedHashMap<String, Object> m = new LinkedHashMap<String, Object>();
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("parmMap");
setParmMap(m);
}
public String submitQuery()
{
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().remove("hitlistData");
if (this.getParmMap().isEmpty())
{
return "";
}
return "/page2.xhtml?faces-redirect=true";
}
private static LinkedHashMap<String, Object> parmMap;
public LinkedHashMap<String, Object> getParmMap()
{
LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("parmMap");
if (null == map)
{
map = new LinkedHashMap<String, Object>();
}
return map;
}
public void setParmMap(LinkedHashMap<String, Object> map)
{
parmMap = map;
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put("parmMap", parmMap);
}
private static SimpleDateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
public void validate(ComponentSystemEvent e) throws ParseException
{
LinkedHashMap parmMap = this.getParmMap();
UIForm queryForm = (UIForm) e.getComponent();
FacesContext fc = FacesContext.getCurrentInstance();
UIInput lastName_c = (UIInput) queryForm.findComponent("lastName");
String lastName = (String) (lastName_c.getValue());
UIInput birthDate_c = (UIInput) queryForm.findComponent("birthDate");
String birthDate = (String) birthDate_c.getValue();
UIInput startDate_c = (UIInput) queryForm.findComponent("startDate");
String startDate = (String) startDate_c.getValue();
try
{
if (null != lastName && lastName.trim().length() > 0)
{
if (null == birthDate || birthDate.length() < 1)
{
birthDate_c.setValid(false);
fc.addMessage(birthDate_c.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, birthDate_c.getRequiredMessage(), birthDate_c.getRequiredMessage()));
}
else
{
birthDate_c.setValid(true);
}
}
else
{
birthDate_c.setValid(true);
}
if (null == startDate || startDate.trim().length() < 1)
{
startDate_c.setValid(false);
fc.addMessage(startDate_c.getClientId(), new FacesMessage(FacesMessage.SEVERITY_ERROR, startDate_c.getRequiredMessage(), startDate_c.getRequiredMessage()));
}
else
{
startDate_c.setValid(true);
}
if (fc.getMessageList().size() > 0)
{
fc.renderResponse();
}
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
It's because you're returning false on focus here:
<p:inputText
...
onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(0).show();return false;" >
</p:inputText>
Returning false causes the event's default behaviour to be blocked.
To fix your problem, simply remove return false; from onfocus attribute of the input component.
<p:inputText
...
onfocus="$('#queryForm\\:msgs > div').hide();$('#queryForm\\:msgs > div').eq(0).show();" >
</p:inputText>
I have a managed bean placed in view scope. Here is the bean:
#ManagedBean(name = "adminController")
#ViewScoped
public class AdminController extends BaseWebController implements Serializable {
private static final long serialVersionUID = 1019716974557397635L;
private transient CustomerDTO customerDTO;
#PostConstruct
public void init() {
customerDTO = new CustomerDTO();
}
public void saveCustomer(ActionEvent event) {
System.out.println(customerDTO.isActive());
try {
getServiceProvider().getCustomerService().addNewCustomer(customerDTO);
getFacesContext().addMessage(null, FacesMessageUtils.getMessageForCustomerAddSuccess(getFacesContext()));
} catch (Throwable throwable) {
getFacesContext().addMessage(null, FacesMessageUtils.getMessageForCustomerAddError(getFacesContext()));
printStackTrace(throwable);
}
}
public CustomerDTO getCustomerDTO() {
return customerDTO;
}
public void setCustomerDTO(CustomerDTO customerDTO) {
this.customerDTO = customerDTO;
}
}
The view is:
<ui:composition 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"
xmlns:pe="http://primefaces.org/ui/extensions">
<p:panel header="#{adbBundle['admin.addCustomerPanel.header']}"
id="addCustomerPanel" toggleable="true">
<p:panelGrid columns="2" id="addCustomerTable"
styleClass="addCustomerTable">
<f:facet name="header">
<p:outputLabel id="header"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.header']}" />
</f:facet>
<p:outputLabel for="customerName"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName']}" />
<h:panelGroup layout="block">
<p:inputText id="customerName" styleClass="customerName"
autocomplete="off"
label="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName']}"
value="#{adminController.customerDTO.customerName}" required="true" />
<pe:tooltip for="customerName"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerName.tooltip']}"
showEffect="slideToggle" hideEffect="slideToggle" showDelay="0"
myPosition="left center" atPosition="right center" />
</h:panelGroup>
<p:outputLabel for="customerId"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerId']}" />
<h:panelGroup layout="block">
<p:inputText id="customerId" autocomplete="off"
label="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerId']}"
value="#{adminController.customerDTO.customerId}" required="true">
<f:validator validatorId="customerIDValidator" />
</p:inputText>
<pe:tooltip for="customerId"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.customerId.tooltip']}"
showEffect="slideToggle" hideEffect="slideToggle" showDelay="0"
myPosition="left center" atPosition="right center" />
</h:panelGroup>
<p:outputLabel for="activeStatus"
value="#{adbBundle['admin.addCustomerPanel.addCustomerTable.activeStatus']}" />
<h:panelGroup layout="block">
<p:selectBooleanCheckbox id="activeStatus" value="#{adminController.customerDTO.active}" />
</h:panelGroup>
<f:facet name="footer">
<p:commandButton value="#{adbBundle['saveButton']}"
actionListener="#{adminController.saveCustomer}"
icon="ui-icon-check" update=":growl, #form" />
</f:facet>
</p:panelGrid>
</p:panel>
</ui:composition>
The problem that I am facing is, after the actionListener successfully executed the input fields are holding the values.
The h:form is not visible in the aforementioned xhtml, it is placed in the parent page as:
<ui:composition 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:p="http://primefaces.org/ui"
template="/WEB-INF/templates/globalTemplate.xhtml">
<ui:define name="title">#{adbBundle['home']}</ui:define>
<ui:define name="content">
<p:growl id="growl" showDetail="true" />
<h:form id="form">
<ui:include src="/WEB-INF/includes/addCustomer.xhtml" />
</h:form>
</ui:define>
</ui:composition>
However if I add customerDTO = new CustomerDTO(); at the end of the actionListener saveCustomer, the inputs are reset.
Is it the way to clear the form? Or there is a better way to achieve this?
To clear form data using ActionEvent on button
public void clear(){
customerDTO = new CustomerDTO();
}
In this page I,m going to let the user to make the password visible by clicking a checkbox. Actually two Inputs (password, conPassword) should hide and another input (passwordV) should be displayed. All these 3 inputs have the same value and needs to keep their values as user switches between these 2 states: (having two secret fields visible or having one plain text field)
I put the page and bean code here:
JSF Page:
<?xml version='1.0' encoding='UTF-8' ?> <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./templates/main_template.xhtml"
xmlns:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns="http://www.w3.org/1999/xhtml">
<ui:define name="subTitle">
:: #{lbls.newEntry} </ui:define>
<ui:define name="content">
<p:panel rendered="#{current.loggedIn}" header="#{lbls.newEntry}" >
<h:form id="frmEntry">
<h:panelGrid columns="3">
<h:panelGroup>
<h:outputLabel for="title" value="#{lbls.title}:"/>
<p:focus for="title"/>
</h:panelGroup>
<p:inputText id="title" value="#{entry.passwordEntry.title}" maxlength="100" label="#{lbls.title}" required="true"/>
<p:message for="title"/>
<h:outputLabel for="description" value="#{lbls.description}:"/>
<p:inputTextarea id="description" value="#{entry.passwordEntry.description}" maxlength="500" rows="3" cols="40" label="#{lbls.description}"/>
<p:message for="description"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<h:outputLabel for="username" value="#{lbls.username}:"/>
<p:inputText id="username" value="#{entry.passwordEntry.username}" maxlength="100" label="#{lbls.username}"/>
<p:message for="username"/>
<h:outputLabel for="password" id="lblPassword" value="#{lbls.password}:" styleClass="#{entry.showPasswords ? 'none' : ''}" />
<p:password id="password" feedback="true" value="#{entry.passwordEntry.password}" match="conPassword" maxlength="100"
label="#{lbls.password}" promptLabel="#{lbls.strengthPromp}" weakLabel="#{lbls.weakPassword}"
goodLabel="#{lbls.goodPassword}" strongLabel="#{lbls.strongPassword}" styleClass="#{entry.showPasswords ? 'none' : ''}"
/>
<p:message id="msgPassword" for="password" class="#{entry.showPasswords ? 'none' : ''}"/>
<h:outputLabel id="lblConPassword" for="conPassword" value="#{lbls.conPassword}:"
styleClass="#{entry.showPasswords ? 'none' : ''}"/>
<p:password id="conPassword" value="#{entry.passwordEntry.password}" label="#{lbls.conPassword}" maxlength="100"
styleClass="#{entry.showPasswords ? 'none' : ''}"/>
<p:message id="msgConPassword" for="conPassword" class="display: #{!entry.showPasswords ? 'none' : ''}"/>
<h:outputLabel id="lblPasswordV" for="passwordV" value="#{lbls.password}:"
styleClass="#{!entry.showPasswords ? 'none' : ''}"/>
<p:inputText id="passwordV" value="#{entry.passwordEntry.password}" maxlength="100"
label="#{lbls.password}"
styleClass="#{!entry.showPasswords ? 'none' : ''}"/>
<p:message id="msgPasswordV" for="passwordV"
class="#{!entry.showPasswords ? 'none' : ''}"/>
<h:outputLabel for="showPasswords" value="#{lbls.showPasswords}:"/>
<p:selectBooleanCheckbox id="showPasswords" label="#{lbls.showPasswords}" value="#{entry.showPasswords}">
<p:ajax process="password passwordV conPassword" update="password passwordV conPassword lblPassword lblPasswordV lblConPassword msgPassword msgConPassword msgPasswordV"/>
</p:selectBooleanCheckbox>
<h:outputText/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<h:outputLabel for="url" value="#{lbls.url}:"/>
<p:inputText id="url" value="#{entry.passwordEntry.url}" maxlength="255" label="#{lbls.url}"/>
<p:message for="url"/>
<h:outputLabel for="ip" value="#{lbls.ip}:"/>
<p:inputText id="ip" value="#{entry.passwordEntry.ip}" maxlength="255" label="#{lbls.ip}"/>
<p:message for="ip"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<h:outputLabel for="tags" value="#{lbls.tags}:"/>
<p:autoComplete id="tags" value="#{entry.selectedTags}"
completeMethod="#{entry.selectTag}" converter="PasswordEntry" multiple="true"
var="tag" itemLabel="#{tag.title}" itemValue="#{tag}" />
<p:message for="tags"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<p:spacer height="10"/>
<h:outputText/>
<h:panelGroup layout="block" styleClass="right-align">
<p:commandButton value="#{lbls.save}" actionListener="#{entry.save(event)}"
update=":growl messages"/>
</h:panelGroup>
<f:facet name="footer">
<p:messages id="messages"/>
</f:facet>
</h:panelGrid>
</h:form>
</p:panel>
<ui:include src="/templates/not_logged_in.xhtml" rendered="!#{current.loggedIn}"/> </ui:define>
</ui:composition>
and Bean:
package package;
#ManagedBean(name = "entry")
#ViewScoped
public class PasswordEntryBean implements Serializable {
//<editor-fold defaultstate="collapsed" desc="FIELDS">
private static final Logger logger = LogUtil.getLogger(PasswordEntryBean.class);
private PasswordEntry passwordEntry;
#ManagedProperty(value = "#{current}")
private CurrentSessionBean current;
private Database database;
private List<PasswordTag> selectedTags = new ArrayList<PasswordTag>();
private Set<PasswordTag> tags;
private boolean showPasswords;
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">
public PasswordEntryBean() {
passwordEntry = new PasswordEntry();
}
#PostConstruct
public void init() {
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="PROPERTIES">
public PasswordEntry getPasswordEntry() {
return passwordEntry;
}
public Database getDatabase() {
return database;
}
public boolean getShowPasswords() {
return showPasswords;
}
public void setShowPasswords(boolean showPasswords) {
this.showPasswords = showPasswords;
}
public void setDatabase(Database database) {
this.database = database;
}
public Set<PasswordTag> getTags() {
return tags;
}
public void setTags(Set<PasswordTag> tags) {
this.tags = tags;
}
public List<PasswordTag> getSelectedTags() {
return selectedTags;
}
public void setSelectedTags(List<PasswordTag> selectedTags) {
this.selectedTags = selectedTags;
}
public void setPasswordEntry(PasswordEntry passwordEntry) {
this.passwordEntry = passwordEntry;
}
public CurrentSessionBean getCurrent() {
return current;
}
public void setCurrent(CurrentSessionBean current) {
this.current = current;
}
//</editor-fold>
}
UPDATED CODE
I just wrote a simpler code in order to make it easier for you to understand my problem:
JSF:
<?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:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
<style type="text/css">
.none {
display: none;
}
</style>
</h:head>
<h:body>
<h1>Register</h1>
<h:form id="frmRegistration">
<h:panelGrid columns="3">
<h:outputLabel value="Username:" for="username"/>
<p:inputText label="username" id="username" value="#{testBean.username}" required="true"/>
<p:message for="username"/>
<h:outputLabel value="Password:" id="lblPassword" for="password" styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
<p:password label="password" id="password" value="#{testBean.password}"
styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
<p:message for="password" id="msgPassword" class="#{!testBean.visiblePassword ? '' : 'none'}"/>
<h:outputLabel value="Confirm Password:" id="lblCpassword" for="cpassword" styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
<p:password label="confirm password" id="cpassword" value="#{testBean.password}"
styleClass="#{!testBean.visiblePassword ? '' : 'none'}"/>
<p:message for="cpassword" id="msgCpassword" class="#{!testBean.visiblePassword ? '' : 'none'}"/>
<h:outputLabel value="Password:" id="lblVpassword" for="vpassword" styleClass="#{testBean.visiblePassword ? '' : 'none'}"/>
<p:inputText label="password" id="vpassword" value="#{testBean.password}"
styleClass="#{testBean.visiblePassword ? '' : 'none'}"/>
<p:message for="vpassword" id="msgVpassword" class="#{testBean.visiblePassword ? '' : 'none'}"/>
<h:outputLabel value="Show password"/>
<p:selectBooleanButton value="#{testBean.visiblePassword}"
onLabel="Yes" offLabel="No">
<p:ajax update="messages password cpassword vpassword lblPassword lblCpassword lblVpassword msgPassword msgCpassword msgVpassword"
process="messages password cpassword vpassword" listener="#{testBean.addMessage}" />
</p:selectBooleanButton>
<f:facet name="footer">
<p:commandButton actionListener="#{testBean.save(event)}" value="Save" update="messages"/>
<p:messages id="messages"/>
</f:facet>
</h:panelGrid>
</h:form>
</h:body>
</html>
AND BEAN:
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
#ManagedBean
#ViewScoped
public class TestBean {
private String username;
private String password;
private boolean visiblePassword;
public void addMessage() {
String summary = visiblePassword ? "Checked" : "Unchecked";
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(summary));
}
public TestBean() {
}
public void save(ActionEvent event) {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public boolean isVisiblePassword() {
return visiblePassword;
}
public void setVisiblePassword(boolean visiblePassword) {
this.visiblePassword = visiblePassword;
}
}
This code can hide two fields and show the third field properly if I do not add process attribute to the <p:ajax tag. But this attribute is needed in order to these fields keep their values when the user switches between two modes (2 secret fields / 1 plain text field)
But it fails!
==========================================================
SECOND UPDATE
I used redisplay and the problem of empty values solved but still the inputs don't hide/show unless I set the update and process to #form which is not good for my case.
<?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:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
<style type="text/css">
.none {
display: none;
}
</style>
</h:head>
<h:body>
<h1>Register</h1>
<h:form id="frmRegistration">
<h:panelGrid columns="3">
<h:outputLabel value="Username:" for="username"/>
<p:inputText label="username" id="username" value="#{testBean.username}" required="true"/>
<p:message for="username"/>
<h:outputLabel value="Password:" id="lblPassword" for="password" rendered="#{!testBean.visiblePassword}"/>
<p:password redisplay="true" label="password" id="password" value="#{testBean.password}"
rendered="#{!testBean.visiblePassword}"/>
<p:message for="password" id="msgPassword" rendered="#{!testBean.visiblePassword}"/>
<h:outputLabel value="Confirm Password:" id="lblCpassword" for="cpassword" rendered="#{!testBean.visiblePassword}"/>
<p:password redisplay="true" label="confirm password" id="cpassword" value="#{testBean.password}"
rendered="#{!testBean.visiblePassword}"/>
<p:message for="cpassword" id="msgCpassword" rendered="#{!testBean.visiblePassword}"/>
<h:outputLabel value="Password:" id="lblVpassword" for="vpassword" rendered="#{testBean.visiblePassword}"/>
<p:inputText label="password" id="vpassword" value="#{testBean.password}"
rendered="#{testBean.visiblePassword}"/>
<p:message for="vpassword" id="msgVpassword" rendered="#{testBean.visiblePassword}"/>
<h:outputLabel value="Show password"/>
<p:selectBooleanButton value="#{testBean.visiblePassword}"
onLabel="Yes" offLabel="No">
<p:ajax update="messages password cpassword vpassword lblPassword lblCpassword lblVpassword msgPassword msgCpassword msgVpassword"
process="password cpassword vpassword" listener="#{testBean.addMessage}" />
</p:selectBooleanButton>
<f:facet name="footer">
<p:commandButton actionListener="#{testBean.save(event)}" value="Save" update="messages"/>
<p:messages id="messages"/>
</f:facet>
</h:panelGrid>
</h:form>
</h:body>
</html>
Your main mistake is that you're toggling visibility of the input fields using CSS in the client side, not using JSF in the server side. So JSF basically never knows which one is shown/hidden. All it knows is that both fields are shown. So it will process the both fields. As you've bound the value of the both fields to the one and same property, it will always end up getting the value of the last processed field.
You need to show/hide the input fields using JSF in the server side instead. You can use the therefor provided rendered attribute.
rendered="#{testBean.visiblePassword}"
The problem is that you're binding the same variable entry.passwordEntry.password to 2 or more fields, so when submitting the <h:form> only one of the values in those fields will be set to entry.passwordEntry.password, the other values will be discarded.
The best way to solve this will be to have different variables for every field you have/need on the form. By looking at your code, it looks like that can be achieved by having 3 PasswordEntry attributes in your bean:
#ManagedBean(name = "entry")
#ViewScoped
public class PasswordEntryBean implements Serializable {
//other attributes...
private PasswordEntry passwordEntry;
private PasswordEntry passwordEntryV;
private PasswordEntry conPasswordEntry;
//<editor-fold defaultstate="collapsed" desc="CONSTRUCTORS">
public PasswordEntryBean() {
passwordEntry = new PasswordEntry();
passwordEntryV = new PasswordEntry();
conPasswordEntry = new PasswordEntry();
}
//getters and setters...
}
JSF Code:
<p:password id="password" feedback="true" value="#{entry.passwordEntry.password}"
match="conPassword" maxlength="100" label="#{lbls.password}"
promptLabel="#{lbls.strengthPromp}" weakLabel="#{lbls.weakPassword}"
goodLabel="#{lbls.goodPassword}" strongLabel="#{lbls.strongPassword}"
styleClass="#{entry.showPasswords ? 'none' : ''}" />
<p:password id="conPassword" value="#{entry.conPasswordEntry.password}"
label="#{lbls.conPassword}" maxlength="100"
styleClass="#{entry.showPasswords ? 'none' : ''}"/>
<p:inputText id="passwordV" value="#{entry.passwordEntryV.password}"
maxlength="100" label="#{lbls.password}"
styleClass="#{!entry.showPasswords ? 'none' : ''}"/>
If you want/need to have the same value in 2 or 3 places, you have to take into account that the bindings should not be in the same <h:form>, otherwise you will have the same problem. You can synchronize the variable values using plain JavaScript (after all, the <p:password> will be <input type="password"> and <p:input> will be <input type="text">) or in the server side when executing an action i.e. the listener that should be executed when selecting a value in your <p:selectBooleanCheckbox>.
I wrote a ViewScoped Managed-Bean and every time I refresh the page in my webbrowser, the Managed-Bean seems to be recreated, article is null, it loads a new article-object and so on. For me it looks like the same behaviour as RequestScoped.
I use Eclipse IDE for Java EE Developers, the newest JDK, Apache Tomcat 7.0.8 and Mojarra 2.0.3.
What is wrong?
Managed-Bean:
...
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
...
#ManagedBean
#ViewScoped
public class CreateArticle {
#ManagedProperty(value = "#{index.facade}")
private PersistenceFacade facade;
private Article article;
private Vector<ArtCategory> artcat;
public CreateArticle() {
artcat = ArtCategory.listArtCat();
}
#PostConstruct
public void postCreateArticle() {
if (article == null) {
try {
article = facade.createArticle();
} catch (DAOException e) {
e.printStackTrace();
}
}
}
public void setFacade(PersistenceFacade facade) {
this.facade = facade;
}
public Vector<ArtCategory> getArtcat() {
return artcat;
}
public Article getArticle() {
return article;
}
public String save() {
try {
facade.save(article);
facade.commit();
} catch (DAOException e) {
e.printStackTrace();
}
FacesMessage message = new FacesMessage(
"Successful!");
FacesContext.getCurrentInstance().addMessage(null, message);
return "/testpage.xhtml";
}
}
createArticle.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">
<h:head>
<title>Create article</title>
</h:head>
<h:body>
<h1>
<h:outputText value="System" />
</h1>
<h2>
<h:outputText value="Test1" />
</h2>
<h3>
<h:outputText value="Test2" />
</h3>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="artname">Articlename</h:outputLabel>
<h:inputText id="artname" value="#{createArticle.article.artname}"
required="true">
<f:ajax event="blur" render="artnameMessage" />
</h:inputText>
<h:message id="artnameMessage" for="artname" />
<h:outputLabel for="briefdesc">Brief description</h:outputLabel>
<h:inputTextarea id="briefdesc"
value="#{createArticle.article.briefdesc}" required="false">
<f:ajax event="blur" render="briefdescMessage" />
</h:inputTextarea>
<h:message id="briefdescMessage" for="briefdesc" />
<h:outputLabel for="price">Price</h:outputLabel>
<h:inputText id="price" value="#{createArticle.article.price}"
required="true">
<f:ajax event="blur" render="priceMessage" />
</h:inputText>
<h:message id="priceMessage" for="price" />
<h:outputLabel for="selectartcat">Article Category</h:outputLabel>
<h:selectOneMenu id="selectartcat"
value="#{createArticle.article.artcatnr}" required="true">
<f:selectItems value="#{createArticle.artcat}" var="artcat"
itemLabel="#{artcat.name}" itemValue="#{artcat.artcatnr}" />
<f:ajax event="blur" render="selectartcatMessage" />
</h:selectOneMenu>
<h:message id="selectartcatMessage" for="selectartcat" />
<h:panelGroup />
<h:commandButton value="Save"
action="#{createArticle.save}">
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:messages globalOnly="true" layout="table" />
</h:panelGrid>
</h:form>
</h:body>
</html>
That's expected behaviour. Surely it will be recreated when you fire brand new HTTP GET requests by refreshing the page in the browser. Otherwise it would act like a session scoped bean and it would make the view scope useless (think about new GET requests in different browser tabs!). It will however not be recreated when you invoke any ajax requests or submit the form in the same view. A request scoped one would be recreated everytime. That's the core point/advantage of a view scoped bean.
Also make sure your implementing Serializable on your ViewScoped beans, just as you would with a SessionScoped bean.