jsf commandbutton action not working ajax [duplicate] - java

This question already has answers here:
Rendering other form by ajax causes its view state to be lost, how do I add this back?
(2 answers)
Closed 9 years ago.
I've got this page, I have two forms on. The second form is loaded (rendered) by ajax. The problem is, that when button of the next form is pressed, the page just reloads itself, not actually calling the method specified in 'action'.
XHTML
<?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="./../WEB-INF/employeeTemplate.xhtml"
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="content">
finding user ...
<h:form id="mainForm">
<h:inputText id="userId" value="#{eFindUser.userId}" />
<h:commandButton value="Render!" action="#{eFindUser.findUser}" >
<f:ajax event="action" execute="userId" render="#all" />
</h:commandButton>
</h:form>
<h:panelGroup id="result">
<h:panelGroup layout="block" rendered="#{eFindUser.notFound}" style="color:red">
User not found
</h:panelGroup>
<h:form>
<h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >
<h:inputHidden value="#{eFindUser.user}" />
<table>
<tr>
<td>Name</td> <td>#{eFindUser.user.name}</td>
</tr>
<tr>
<td>Balance:</td> <td>#{eFindUser.user.account.balance}</td>
</tr>
<tr>
<td><h:commandButton value="update balance" action="#{eFindUser.process()}" /></td>
</tr>
</table>
</h:panelGroup>
</h:form>
</h:panelGroup>
</ui:define>
</ui:composition>
Backing bean
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package backingbeans;
import entities.User;
import java.io.Serializable;
import java.util.Random;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import javax.validation.constraints.NotNull;
import stateless.EmployeeFacade;
/**
*
* #author Martin
*/
#ManagedBean(name="eFindUser")
#ViewScoped
public class EFindUserManagedBean implements Serializable{
private static final long serialVersionUID = -7106162864352727534L;
private boolean responseRendered = false;
private boolean notFound = false;
#NotNull
private Long userId;
private User user;
#Inject
private EUpdateBalanceManagedBean updateBalance;
#Inject
private EmployeeFacade employeeFacade;
/**
* Creates a new instance of EFindUserManagedBean
*/
public EFindUserManagedBean() {
}
public void findUser() {
if(new Random().nextDouble() < 0.3) {
notFound = true;
responseRendered = false;
} else {
notFound = false;
responseRendered = true;
user = employeeFacade.getUserById(3L);
}
}
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(boolean responseRendered) {
this.responseRendered = responseRendered;
}
public boolean isNotFound() {
return notFound;
}
public void setNotFound(boolean notFound) {
this.notFound = notFound;
}
public Long getUserId() {
return userId;
}
public void setUserId(Long userId) {
System.out.println("blah");
this.userId = userId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
System.out.println("setting user");
this.user = user;
}
public String process() {
updateBalance.setUser(user);
System.out.println("process");
return "/employee/updateBalance.xhtml?faces-redirect=true";
}
}
When I click the first 'Render!'-labeled button, it works like charm. Second form is loaded and ready to work. When I click the next 'update balance'-labeled button, the page just reloads which it shouldn't, of course. It should redirect to "/employee/updateBalance". Or it should at least call the process method.
Thanks a lot
EDIT: #BalusC is right, the answer is in previous question

The culprit can be found in <h:inputHidden> tag of the second form:
<h:form>
<h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >
<h:inputHidden value="#{eFindUser.user}" />
</h:panelGroup>
</h:form>
Most probably its bound value, eFindUser.user is of type User and when you submit that form JSF doesn't know how to assign a string representation of user with a User object.
Hence, there is a conversion error, in which case action method is not called, according to JSF lifecycle. Additionally, you would have known that if you had <h:messages> in your view.
What can be done is the following:
Assign converter to your input like <h:inputHidden value="#{eFindUser.user}" converter="userConverter"/> with a #FacesConverter implemented. More details can be found here.
Bind <h:inputHidden> to a String, so that no converter would be needed: <h:inputHidden value="#{eFindUser.user.userNickname}"> or to an Integer in a similar way.

modify
<h:commandButton value="update balance" action="#{eFindUser.process()}" />
to
<h:commandButton value="update balance" action="#{eFindUser.process}" />
el expression can't contain “()”

Related

FindComponent + set invalid challenge

I have a this simplified form to show the challenge:
It is a form with multiple tabs (2 in this MVCE).
My goal is to highlight both fields in case of validation failure (but only for tab it is failing for).
TabView (backing bean)
package betlista.so.pf.findComponent;
import com.sun.faces.component.visit.FullVisitContext;
import org.primefaces.PrimeFaces;
import org.springframework.stereotype.Component;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import java.util.LinkedList;
import java.util.List;
#Component
public class TabView {
List<TabData> tabData = new LinkedList<>();
{
tabData.add(new TabData("name 1", "val1-a", null));
tabData.add(new TabData("name b", "val1-b", "val2-b"));
}
public List<TabData> getTabsData() {
return tabData;
}
public void save() {
boolean isValid = isValid();
if (isValid) {
// continue ...
}
}
private boolean isValid() {
boolean isOk = isOk();
if (isOk) {
return true;
}
FacesMessage message = new FacesMessage("Not saved!");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
final UIViewRoot viewRoot = context.getViewRoot();
List<UIInput> componentList = new LinkedList<>();
viewRoot.visitTree(new FullVisitContext(context), new VisitCallback() {
#Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target != null) {
final String id = target.getId();
if ("val1".equals(id) || "val2".equals(id)) {
if (target instanceof UIInput) {
componentList.add((UIInput) target);
}
}
}
return VisitResult.ACCEPT;
}
});
for (UIInput uiInput: componentList) {
uiInput.setValid(false);
}
context.validationFailed();
PrimeFaces.current().ajax().update("form");
final UIComponent val1 = context.getViewRoot().findComponent("val1");
return false;
}
private boolean isOk() {
return false;
}
}
in this simplified version isOk() returns false.
In a validation I know whether data for 1st or second tab is not ok and I'm trying to find a way how to highlight those two fields in tab.
I tried initially context.getViewRoot().findComponent(...), but I'm not able to "find it" (returns null). So to have access to the components I used this:
List<UIInput> componentList = new LinkedList<>();
viewRoot.visitTree(new FullVisitContext(context), new VisitCallback() {
#Override
public VisitResult visit(VisitContext context, UIComponent target) {
if (target != null) {
final String id = target.getId();
if ("val1".equals(id) || "val2".equals(id)) {
if (target instanceof UIInput) {
componentList.add((UIInput) target);
}
}
}
return VisitResult.ACCEPT;
}
});
so I have (in this case) all 4 components (but let say only those for first tab are invalid).
I'm trying to find a way how to identified which component belong to which tab (not sure whether to rely on a an order in list).
I was trying dynamic ID's, but it's not working, e.g. I added tab name (tabName)as attribute and used
<p:inputText id="#{cc.attr.tabName}-val2" ... />
I found no way how to add some custom flag/attribute whatever to be able to link component to a tab.
I was reading that ID can be dynamic once I'd use EL custom function (I mean I can use concatenation), but I was not able to find a resource describing it (I have no web.xml).
Code is available in GitHub.
myTab.xhtml (custom component)
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:p="http://primefaces.org/ui"
xmlns:composite="http://java.sun.com/jsf/composite">
<composite:interface>
<composite:attribute name="data" required="true" type="betlista.so.pf.findComponent.TabData" />
</composite:interface>
<composite:implementation>
<div class="ui-g">
<div class="ui-g-12">
<div class="ui-g-6">
<p:outputLabel value="Val 1:"/>
</div>
<div class="ui-g-6">
<p:inputText id="val1" value="#{cc.attrs.data.val1}" widgetVar="#{cc.attrs.data.tabName}-val1"/>
</div>
</div>
<div class="ui-g-12">
<div class="ui-g-6">
<p:outputLabel value="Val 2:"/>
</div>
<div class="ui-g-6">
<p:inputText id="val2" readonly="true" value="#{cc.attrs.data.val2}" widgetVar="#{cc.attrs.data.tabName}-val2"/>
</div>
</div>
</div>
</composite:implementation>
</html>
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:p="http://primefaces.org/ui"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:comp="http://xmlns.jcp.org/jsf/composite/comp">
<h:head>
<h:outputScript library="webjars" name="font-awesome/5.5.0/js/all.js"/>
</h:head>
<h:body styleClass="mainBody">
<h:form id="form">
<p:tabView id="tabView" value="#{tabView.tabsData}" var="tabVar">
<p:tab id="tab" title="#{tabVar.tabName}">
<comp:myTab data="#{tabVar}" />
</p:tab>
</p:tabView>
<p:commandButton value="Save" action="#{tabView.save()}" process="#form" update="#form" />
<p:growl id="growl" life="3000"/>
</h:form>
</h:body>
</html>
I got very confused by debugger...
The simplest solution is to add label like this:
<p:inputText id="val1" value="#{cc.attrs.data.val1}" label="someLabel1" />
...what I missed earlier is, that label is not a field therefor it was difficult to find it, it is available under stateHelper:
Probably better solution (despite label I cannot see in generated HTML) is to use custom attribute like this (I'd bet I tried that as well, apparently not):
<p:inputText id="val2" readonly="true" value="#{cc.attrs.data.val2}">
<f:attribute name="someAttribute" value="value2" />
</p:inputText>
and it's easily accessible:

Get values from Selectiomenu with PrimeFaces

I have the following page xhtml where i have to get some values for populate a DB table. The problem are the selection menu that don't work. Actually, the values of the selections are chosen from the database and are displayed but the values aren't taken when i use the button:
<!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">
<h:head>
<title>Add a Default Package</title>
</h:head>
<h:body>
<h:form>
<p:panel header="DefaultPackage Form">
<h:panelGrid columns="3" id="regGrid">
<h:outputLabel for="Name">Name:</h:outputLabel>
<p:inputText id="Name" value="#{addDefaultPackageBean.defpackDTO.name}" />
<p:message for="Name" />
<h:outputLabel for="location">Location:</h:outputLabel>
<p:inputText id="location" value="#{addDefaultPackageBean.defpackDTO.location}" />
<p:message for="location" />
<h:selectOneMenu value="#{addDefaultPackageBean.nameFlies}">
<f:selectItems value="#{addDefaultPackageBean.elelisfly}" var="ElementDTO" itemValue="#{ElementDTO.location}" itemLabel="#{ElementDTO.location}"/>
</h:selectOneMenu>
<h:selectOneMenu value="#{addDefaultPackageBean.nameHotels}">
<f:selectItems value="#{addDefaultPackageBean.elelishotel}" var="ElementDTO" itemValue="#{ElementDTO.location}" itemLabel="#{ElementDTO.location}"/>
</h:selectOneMenu>
</h:panelGrid>
<p:commandButton value="Add" update="regGrid" action="#{addDefaultPackageBean.add()}" />
</p:panel>
</h:form>
</h:body>
</html>
The image displayed is:
The bean page:
package beans;
import java.util.ArrayList;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import elementManagement.ElementMgr;
import elementManagementDTO.ElementDTO;
import DefaultPackageManagement.DefaultPackageMgr;
import DefaultPackageManagementDTO.DefaultPackageDTO;
#ManagedBean(name="addDefaultPackageBean") //come viene richiamato
#RequestScoped
public class AddDefaultPackageBean {
#EJB
private DefaultPackageMgr defpackMgr;
private DefaultPackageDTO defpackDTO;
private ArrayList<ElementDTO> elelisfly;
private ArrayList<ElementDTO> elelishotel;
private String nameFlies;
private String nameHotels;
#EJB
private ElementMgr elemMgr;
public AddDefaultPackageBean() {
defpackDTO = new DefaultPackageDTO();
defpackDTO.setElem(new ArrayList<ElementDTO>());
}
#PostConstruct
public void init()
{
setElelisfly(elemMgr.getAllFlights());
setElelishotel(elemMgr.getAllHotels());
}
public String add() {
this.AssignElemFlyFromSelection();
this.AssignElemHotelFromSelection();
defpackMgr.save(defpackDTO);
return "/employee/index?faces-redirect=true";
}
public DefaultPackageDTO getDefpackDTO() {
return defpackDTO;
}
public void setDefpackDTO(DefaultPackageDTO defpackDTO) {
this.defpackDTO = defpackDTO;
}
public ArrayList<ElementDTO> getElelisfly() {
return elelisfly;
}
public void setElelisfly(ArrayList<ElementDTO> elelisfly) {
this.elelisfly = elelisfly;
}
public ArrayList<ElementDTO> getElelishotel() {
return elelishotel;
}
public void setElelishotel(ArrayList<ElementDTO> elelishotel) {
this.elelishotel = elelishotel;
}
public String getNameFlies() {
return nameFlies;
}
public void setNameFlies(String nameFlies) {
this.nameFlies = nameFlies;
}
public String getNameHotels() {
return nameHotels;
}
public void setNameHotels(String nameHotels) {
this.nameHotels = nameHotels;
}
private void AssignElemFlyFromSelection()
{
for (ElementDTO elem:this.elelisfly)
{
if(elem.getLocation()==this.nameFlies)
{
this.defpackDTO.getElem().add(elem);
}
}
}
private void AssignElemHotelFromSelection()
{
for (ElementDTO elem:this.elelishotel)
{
if(elem.getLocation()==this.nameHotels)
{
this.defpackDTO.getElem().add(elem);
}
}
}
}
Thank you for the help!
You're comparing Java String objects using == operator instead of .equals() method. That causes a comparison between Object references to be performed, instead of implemented String comparison.
elem.getLocation()==this.nameFlies
and
elem.getLocation()==this.nameHotels
Change them for String#equals().
See also:
Java String.equals versus ==
Add process to your commandobutton.
Like this:
<p:commandButton process="#form" value="Add" update="regGrid" action="#{addDefaultPackageBean.add()}" />

rendering <h:panelGroup> by ajax in jsf

I've got this piece of code, which doesn't do exactly what I thought. I try to set property by Ajax and then re-render one component. My .xhtml looks like this
<h:form>
<h:commandButton value="Render!" >
<f:ajax render=":result" listener="#{eFindUser.findUser}" />
</h:commandButton>
</h:form>
<h:panelGroup id="result" layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
the backing bean looks like this
#Named(value = "eFindUser")
#ViewScoped
public class EFindUserManagedBean implements Serializable{
private boolean responseRendered = false;
/**
* Creates a new instance of EFindUserManagedBean
*/
public EFindUserManagedBean() {
}
public void findUser(AjaxBehaviorEvent abe) {
responseRendered = !responseRendered;
System.out.println("finding..... ("+ responseRendered+")" + this);
}
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(boolean responseRendered) {
this.responseRendered = responseRendered;
}
}
When I re-click the button, the property is not changed. There is a message in serverlog, which says
INFO: finding..... (true)backingbeans.EFindUserManagedBean#5736b751
INFO: finding..... (true)backingbeans.EFindUserManagedBean#23959d6f
Clearly there is some issue with the managed bean as it is created every time there is a request even if it should be view-scoped.
What should I change so the panelgroup(id:"result") could change it's visibility? No richfaces or any other technology allowed.
Thank you very much for your answers
You can't render dynamically a JSF component that is not rendered all time. The object must exist in the DOM client side. When using rendered="false", the output is not generated server side.
Change your code like this :
<h:form>
<h:commandButton value="Render!" >
<f:ajax render=":result" listener="#{eFindUser.findUser}" />
</h:commandButton>
</h:form>
<h:panelGroup id="result">
<h:panelGroup layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
</h:panelGroup>
With that, the DOM will always contain something with the id="result".
This works for me:
<ui:composition>
<h:form id="mainForm">
<h:commandButton value="Render!" action="#{eFindUser.findUser}">
<f:ajax event="action" render=":result" />
</h:commandButton>
</h:form>
<h:panelGroup id="result" layout="block" rendered="#{eFindUser.responseRendered}" >
This is some text that is supposed to be rendered later
</h:panelGroup>
</ui:composition>
Bean:
#ManagedBean
#ViewScoped
public class EFindUser implements Serializable{
private static final long serialVersionUID = -7106162864352727534L;
private boolean responseRendered = false;
public EFindUser() {
}
public void findUser() {
responseRendered = !responseRendered;
System.out.println("finding..... ("+ responseRendered+")" + this);
}
public boolean isResponseRendered() {
return responseRendered;
}
public void setResponseRendered(boolean responseRendered) {
this.responseRendered = responseRendered;
}
}
Take a look on JSF 2.0 + Ajax Hello World Example

How to create tabs - Jquery or JSF

I want to create JSF page with tabs. Something like this. But I wonder if I choose to do this with Jquery can I implement lazy loading - when I click a tab on the JSF page the content is generated when the tab is opened. Is it possible to implement lazy loading of tabs in pure JSF? And I suppose that I can easily implement AJAX in both cases.
Best wishes
The Primefaces Tabview component supports lazy loading.
Quote from the showcase:
Tab contents can be lazy loaded with ajax as well, when dynamic
attribute is set to "true" only the active tab's content will be
rendered and clicking on a lazy tab will fetch the tab contents with
ajax. This behavior is handy to save bandwith and reduce page size
when dealing with tabs having a lot of content.
Quick example from the showcase:
<h:form id="form">
<p:tabView id="tabView" dynamic="true" cache="true">
// tabs
</p:tabView>
</h:form>
The cache attribute is used to prevent ajax reloading of tab content if you toggle between tabs.
Note: If you want your tabs beans be Session Scope then read instructions in the buttom of the Answer...
Since you are don't want to use any third party Libarary here is a PureJSF + jQuery example
JSF + Jquery + Ajax Lazy Loading + View Scope Beans Example...
B.T.W here is how it looks like eventually :
You can look at the web server console for the print outs of #PostConstruct and the #PreDestroy when you click on each tab...
The content of the tab - the xhtml page and its bean will be loaded upon tab click (Lazy Loading) and will be destroyed upon click on other tab,
I suggest you to create a new project and slowly place all the files inside it and start playing and looking into it... its 100% working , but I placed some print outs just to see that it is really working...
The Example is very simple and straight forward....
First Of all go to jQueryUI and download it(1.8.18)
and place jquery-1.7.1_.min.js and jquery-ui-1.8.18.custom.min.js in WebContent\resources\js and jquery-ui-1.8.18.custom.css in WebContent\resources\css
Now to the other files...
myTabs.xhtml
<!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">
<h:head>
<h:outputScript library="js" name="jquery-1.7.1_.min.js" target="head" />
<h:outputScript library="js" name="jquery-ui-1.8.18.custom.min.js" target="head" />
<h:outputStylesheet library="css" name="jquery-ui-1.8.18.custom.css" target="head" />
<h:outputScript library="js" name="mytabs.js" target="head" />
</h:head>
<h:body>
<f:view>
<h:form prependId="false">
<h:panelGroup id="tabs" layout="block">
<ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<li>#{tab.tabid}</li>
<h:commandButton id="button_#{tab.tabid}" value="TabClick" action="#{myTabs.switchPages(tab.tabid)}" style="display:none">
<f:ajax render="tabs"></f:ajax>
</h:commandButton>
</c:forEach>
</ul>
<c:forEach items="#{myTabs.tabs}" var="tab">
<h:panelGroup id="#{tab.tabid}" layout="block" rendered="#{tab.tabid eq myTabs.selectedTab}">
<ui:include src="#{tab.tabfilename}"></ui:include>
</h:panelGroup>
</c:forEach>
</h:panelGroup>
</h:form>
</f:view>
</h:body>
</html>
MyTabs.java
package pack;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class MyTabs{
#PostConstruct
public void init(){
tabs = new ArrayList<MyTabObject>();
tabs.add(new MyTabObject("tab1.xhtml", "tab1"));
tabs.add(new MyTabObject("tab2.xhtml", "tab2"));
tabs.add(new MyTabObject("tab3.xhtml", "tab3"));
}
String selectedTab="tab1";
public String getSelectedTab() {
return selectedTab;
}
public void setSelectedTab(String selectedTab) {
this.selectedTab = selectedTab;
}
public String switchPages(String selTab) {
selectedTab = selTab;
return "myTabs.xhtml";
}
List<MyTabObject> tabs;
public List<MyTabObject> getTabs() {
return tabs;
}
public void setTabs(List<MyTabObject> tabs) {
this.tabs = tabs;
}
}
MyTabObject
package pack;
public class MyTabObject{
String tabfilename;
String tabid;
public String getTabfilename() {
return tabfilename;
}
public void setTabfilename(String tabfilename) {
this.tabfilename = tabfilename;
}
public String getTabid() {
return tabid;
}
public void setTabid(String tabid) {
this.tabid = tabid;
}
public MyTabObject(String tabfilename, String tabid) {
super();
this.tabfilename = tabfilename;
this.tabid = tabid;
}
}
Tab1Page , (Tab2Page and Tab3Page are exactly the same , just change the number in all places)
package pack;
import java.io.Serializable;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class Tab1Page implements Serializable{
/**
*
*/
private static final long serialVersionUID = 254415216070877770L;
// Constants
public final static String hashKey = "tab1PageTab";
public String actionString = "";
#PostConstruct
public void post(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t#PostConstruct...");
}
#PreDestroy
public void destroy(){
Format formatter;
Date date = new Date();
// Time formate 01:12:53 AM
formatter = new SimpleDateFormat("hh:mm:ss a");
tabName = formatter.format(date);
System.out.println("Tab1Page\t"+tabName+"\t#PreDestroy...");
}
String tabName;
public String getTabName() {
return this.getClass().getName().substring(this.getClass().getName().lastIndexOf("."))+"\t"+tabName;
}
public void setTabName(String tabName) {
this.tabName = tabName;
}
public String getActionString() {
return actionString;
}
public void setActionString(String actionString) {
this.actionString = actionString;
}
}
tab1.xhtml (tab2.xhtml and tab3.xhtml are exactly the same - just replace the numbers)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:c="http://java.sun.com/jsp/jstl/core">
<h:panelGroup>
<h:form>
<h:outputText value="#{tab1Page.tabName}" />
</h:form>
</h:panelGroup>
</ui:composition>
and to the last file
mytabs.js (place it in WebContent\resources\js)
$(document).ready(function () {
$("#tabs").tabs();
});
$(window).load(function() {
jsf.ajax.addOnEvent(function (data) {
if (data.status === "success") {
$("#tabs").tabs();
}
});
});
In order to use Session Scope Beans:
The method switchPages in MyTabs.java should be void and not to return anything, like this
public void switchPages(String selTab) {
selectedTab = selTab;
}
It's not a problem at all implement an ajax tab with jQuery UI.
See the documentation of jQuery Tabs with ajax here and click on "view source" to find the code you need.
You can look at the book Core Java Server Faces third edition page 339 to see how you can implement simple tabs with h:panelGrid.
The output is something like this:
This is the code example from the book:
...
<h:form>
<h:panelGrid styleClass="tabbedPane" columnClasses="displayPanel">
<!-- Tabs -->
<f:facet name="header">
<h:panelGrid columns="4" styleClass="tabbedPaneHeader">
<h:commandLink tabindex="1"
title="#{msgs.jeffersonTooltip}"
styleClass="#{tp.jeffersonStyle}"
actionListener="#{tp.jeffersonAction}">
#{msgs.jeffersonTab}
</h:commandLink>
...
</h:panelGrid>
</f:facet>
<!-- Tabbed pane content -->
<ui:include src="washington.xhtml" />
<ui:include src="roosevelt.xhtml" />
<ui:include src="lincoln.xhtml" />
<ui:include src="jefferson.xhtml" />
</h:panelGrid>
</h:form>
...
This is the description:
The tabbed pane is implemented with h:panelGrid. Because we do not specify
the columns attribute, the panel has one column. The panel’s header—defined
with an f:facet tag—contains the tabs, which are implemented with another
h:panelGrid that contains h:commandLink tags for each tab. The only row in the panel
contains the content associated with the selected tab.
When a user selects a tab, the associated action listener for the command link is
invoked and modifies the data stored in the backing bean. Because we use a
different CSS style for the selected tab, the styleClass attribute of each h:commandLink
tag is pulled from the backing bean with a value reference expression.
As you can see from the top picture in Figure 8–11, we have used the title
attribute to associate a tooltip with each tab. Another accessibility feature is the
ability to move from one tab to another with the keyboard instead of the
mouse. We implemented that feature by specifying the tabindex attribute for
each h:commandLink.
The content associated with each tab is statically included with the JSP include
directive. For our application, that content is a picture and some text, but
you could modify the included JSF pages to contain any set of appropriate
components. Notice that even though all the JSF pages representing content are
included, only the content associated with the current tab is rendered. That is
achieved with the rendered attribute—for example, jefferson.xhtml looks like this:
Putting It All Together
<h:panelGrid columns="2" columnClasses="presidentDiscussionColumn"
rendered="#{tp.jeffersonCurrent}">
<h:graphicImage value="/images/jefferson.jpg"/>
<span class="tabbedPaneContent">"#{msgs.jeffersonDiscussion}"</span>
</h:panelGrid>
Figure 8–12 shows the directory structure for the tabbed pane application and
Listings 8–14 through 8–17 show the most important files.
Unfortunately I don't know how to add lazy loading and AJAX support to this code.

getting values from primefaces components

I have facelets page and managed bean that is associated with it.
i have used primefaces components and my problem is i want to get the values selected by the user of each components when a commandbutton is clicked.
when i try to write a JoptionPane or system.out.print it does not work. i have set the commandbutton action property to btnsearchFlight method whcih is found in the managedbean. so any one what is the problem what i am missing. Or an example will be very much appreciated.
Here is the Facelets 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: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">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link href="./resources/css/default.css" rel="stylesheet" type="text/css" />
<link href="./resources/css/cssLayout.css" rel="stylesheet" type="text/css" />
<title>Airline Travel Planner</title>
</h:head>
<h:body>
<h:form id="form">
<div id="top">
<ui:insert name="top">AirLine Travel Planner</ui:insert>
</div>
<div>
<div id="left">
<ui:insert name="left"></ui:insert>
</div>
<div>
<div id="right">
<ui:insert name="right"></ui:insert>
</div>
<div id="content" class="right_content" style="height: 500px">
<ui:insert name="content">
<p:selectOneRadio binding="#{calendarBean1.rdbTripType}" id="rdbTripType" value="#{calendarBean1.rdbTripType}">
<f:selectItem itemLabel="One Way" itemValue="1" />
<f:selectItem itemLabel="Round Trip" itemValue="2" />
</p:selectOneRadio>
<br/>
<h:outputLabel>From:</h:outputLabel>
<p:selectOneMenu value="#{calendarBean1.cityInfo}" style="" effect="fold" editable="true">
<f:selectItems value="#{calendarBean1.cityInfo}" />
</p:selectOneMenu>
<h:outputLabel style="position: relative">To:</h:outputLabel>
<p:selectOneMenu value="#{calendarBean1.cityInfo}" effect="fold" editable="true">
<f:selectItems value="#{calendarBean1.cityInfo}" />
</p:selectOneMenu>
<br/><br/>
<h:outputLabel>Depart On:</h:outputLabel>
<p:calendar value="#{calendarBean1.date3}" id="popupButtonDepartOn" showOn="button" />
<h:outputLabel>Arrive On:</h:outputLabel>
<p:calendar value="#{calendarBean1.date2}" id="popupButtonArriveOn" showOn="button" />
<br/> <br/>
<h:outputText value="Passenger Type" />
<p:selectOneMenu id="selectOneMenuPassengerType" binding="#{calendarBean1.selectOneMenuPassengerType}" value="#{calendarBean1.selectOneMenuPassengerType}" >
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItem itemLabel="Adult" itemValue="1" />
<f:selectItem itemLabel="Child" itemValue="2" />
<f:selectItem itemLabel="Infant" itemValue="3" />
</p:selectOneMenu>
<br/> <br/>
<p:selectBooleanCheckbox value="#{calendarBean1.lowestFareChecked}" />
<h:outputText value="Lowest Fare" />
<br/>
<p:commandButton id="btnSearchFlight" value="Search" action="#{calendarBean1.searchFlight}" >
</p:commandButton>
Here is the managed bean class
package test.sample;
import java.io.Serializable;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;
import javax.faces.bean.ManagedBean;
import javax.faces.model.SelectItem;
import javax.swing.JOptionPane;
import org.primefaces.component.commandbutton.CommandButton;
import org.primefaces.component.selectonemenu.SelectOneMenu;
import org.primefaces.component.selectoneradio.SelectOneRadio;
import storageMethods.FlightMethod;
/**
*
* #author Nati
*/
#ManagedBean(name = "calendarBean1")
public class CalendarBean1 implements Serializable{
/**
* Creates a new instance of CalendarBean1
*/
public CalendarBean1() {
}
private Date date1;
private Date date2;
private Date date3;
private boolean lowestFareChecked;
public boolean isLowestFareChecked() {
return lowestFareChecked;
}
public void setLowestFareChecked(boolean lowestFareChecked) {
this.lowestFareChecked = lowestFareChecked;
}
public Date getDate1() {
return date1;
}
public void setDate1(Date date1) {
this.date1 = date1;
}
public Date getDate2() {
return date2;
}
public void setDate2(Date date2) {
this.date2 = date2;
}
public Date getDate3() {
return date3;
}
public void setDate3(Date date3) {
this.date3 = date3;
}
private SelectOneRadio rdbTripType = new SelectOneRadio();
public SelectOneRadio getRdbTripType() {
return rdbTripType;
}
public void setRdbTripType(SelectOneRadio rdbTripType) {
this.rdbTripType = rdbTripType;
}
public CommandButton btnSearchFlight = new CommandButton();
public CommandButton getBtnSearchFlight() {
return btnSearchFlight;
}
public void setBtnSearchFlight(CommandButton btnSearchFlight) {
this.btnSearchFlight = btnSearchFlight;
}
private SelectOneMenu selectOneMenuPassengerType = new SelectOneMenu();
public SelectOneMenu getSelectOneMenuPassengerType() {
return selectOneMenuPassengerType;
}
public void setSelectOneMenuPassengerType(SelectOneMenu selectOneMenuPassengerType) {
this.selectOneMenuPassengerType = selectOneMenuPassengerType;
}
public ArrayList<SelectItem> CityInfo;
public ArrayList<SelectItem> getCityInfo() {
CityInfo = CityInfo();
return CityInfo;
}
public void setCityInfo(ArrayList<SelectItem> CityInfo) {
this.CityInfo = CityInfo;
}
public String SearchFlight() {
// JOptionPane.showMessageDialog(null, rdbTripType.getValue().toString());
// JOptionPane.showMessageDialog(null, selectOneMenuPassengerType.getValue().toString());
JOptionPane.showMessageDialog(null,date3);
// System.out.print("hi");
// System.out.print(isLowestFareChecked());
return null;
}
}
Maybe just a typo when posting on stackoverflow, but your method is Capitalized:
SearchFlight
And your action in .xhtml button is lowercase.
action="#{calendarBean1.searchFlight}
Shouldn't it be
public String searchFlight() {
I never used Swing components in a JSf franework. But the system.out should work when commented out. If you method is called. Don't you get any errors in your logs?
I think you mixed webapp development (JSF) with desktop development (Swing). With JSF you don't need to create a backing bean component for every single facelet component. You don't need
org.primefaces.component.commandbutton.CommandButton
org.primefaces.component.selectonemenu.SelectOneMenu
org.primefaces.component.selectoneradio.SelectOneRadio
in your bean if you only want to bind the input values of these components.
Of course in some situations you will get benefits from component binding but it is not necessary in your example.
In the facelet you use the value attribute and the binding attribute, but they have the same content.
If you are only interested in input values, the value attribute is all you need. Let this attribute point to a backing bean field that only will hold the value, e.g. an int or String.

Categories

Resources