Reloading the same page based on a toggle button preserving the paramters - java

I have a page where I have a static list containing the list of products which are again grouped into product groups.I have a toggle button in the JSP page which shuffles between the enabled and disabled products .Code for my toggle button is as follows
<h:commandButton value="retrieve" image="#{displayProductsBean.productsToggleImage}" actionListener="#{displayProductsBean.fetchProductsBasedOnStatus}">
<c:choose>
<c:when test="${displayProductsBean.productFetchCriteria=='0'}">
<f:attribute name="buttonSelected" value="1" />
</c:when>
<c:otherwise>
<f:attribute name="buttonSelected" value="0" />
</c:otherwise>
</c:choose>
</h:commandButton>
Now in the managed bean I am able to get the value of the button selected and have logic to retrieve either enabled or disabled products
But I don't know how would I get back to the same page and also I don't want the list to be reloaded again from the DB.Code in my bean class is as follows
public void fetchProductsBasedOnStatus(ActionEvent event)
{
System.out.println("The fetchProductsBasedOnStatus in bean is called");
String selected = (String) event.getComponent().getAttributes().get("buttonSelected");
System.out.println("The value of toggle button is"+selected);
setProductFetchCriteria(Integer.parseInt(selected));
System.out.println("The value of toggle button is"+this.toString());
}
Somebody please help me resolve this .....

But I don't know how would I get back to the same page
Just return null or void in action method.
and also I don't want the list to be reloaded again from the DB
Just don't do that? If you keep the bean in the view scope and load the lists in the (post)constructor, then the same lists will be kept as long as the enduser is interacting with the same view. You should only not use JSTL tags as it breaks the view scope.
Your code can be simplified as follows:
<h:commandButton value="retrieve" image="#{bean.showDisabledProducts ? 'enabled' : 'disabled'}.png" action="#{bean.toggle}">
<f:ajax render="#form" />
</h:commandButton>
<h:dataTable value="#{bean.products}" ...>
...
</h:dataTable>
with
#ManagedBean
#ViewScoped
public class Bean {
private boolean showDisabledProducts;
private List<Product> enabledProducts;
private List<Product> disabledProducts;
#EJB
private ProductService service;
#PostConstruct
public void init() {
enabledProducts = service.listEnabledProducts();
disabledProducts = service.listDisabledProducts();
}
public void toggle() {
showDisabledProducts = !showDisabledProducts;
}
public List<Product> getProducts() {
return showDisabledProducts ? disabledProducts : enabledProducts;
}
public boolean isShowDisabledProducts() {
return showDisabledProducts;
}
}

Related

JSF - Can't display list of objects from ManagedBean

Someone maybe knows why I can't display list of categories in my app. File categories.xhtml shows only word Categories. Class Category sets id and name in constructor.
categories.xhtml
<ui:component>
<h:form>
<h4>Categories</h4>
<ul>
<ui:repeat var="category" value="#{categoriesBean.modelCategories}">
<li><h:outputText value="#{category.name}">
</h:outputText>
</li>
</ui:repeat>
</ul>
</h:form>
</ui:component>
CategoriesBean.java
#ManagedBean
#RequestScoped
public class CategoriesBean {
private ListDataModel<Category> modelCategories = new ListDataModel<Category>();
public ListDataModel<Category> getModelCategories() {
return modelCategories;
}
public void setModelCategories(ListDataModel<Category> modelCategories) {
this.modelCategories = modelCategories;
}
public CategoriesBean() {
modelCategories.setWrappedData(DAO.getDAO().getCategories());
}
}
DAO.java
public class DAO {
private static DAO instance = new DAO();
private List<Category> categories = new ArrayList<Category>();
{
Category smartphones = new Category(1, "Smartphones");
Category consoles = new Category(2, "Consoles");
categories.add(smartphones);
categories.add(consoles);
}
public static DAO getDAO() {
return instance;
}
public List<Category> getCategories() {
return this.categories;
}
Here is site source:
<form id="j_idt2" name="j_idt2" method="post" action="/Shop/categories.xhtml" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="j_idt2" value="j_idt2" />
<ul>
</ul><input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="H4sIAAAAAAAAAJVSQWvUQBR+Tbp2G1Zpt9KL6KkIgmSp2IuLuIvt0sXULqSCxYPOZqebWSfJOPOym/RQ8B8InoSKVw/e/AXVgyAo6FFv3j16dyaN3R704EBe8vK+9+Z773tvfkJFKAmLIzImboqMu5tEhVtEVOa+Hb1ffvTFBqsDDk/IoEMCTGQX5jGUVIUJH2TiVgvMqU2q2i7ox0Y4M3rIBriaSlh64BV1OYmH7nZ/RANsPvt8/9WCusItgEzohIrQJ30CB2Ab70CCa3Iyd48EVLlBEokkpjG697q3/3yv9GQiqMT8Ds0VlKeuC0o4N71wI06j00GB4BBEyfopUqWbXpo23ZaS5B5TmD39evHFB/LShpkuzCq2TwuW9mTWWJ10+e/sfCRIN/VMqPTJmMrdj29vPj/8tGWB5cF8wIlSd0lEEerFSBqGYcPXZOJh0wNH6ZxBUQNh+RjBkoZPJSOc7ZM+p81MiLEZEyhja7qbS/p6V6VxScZYTlG57V7P626slzjNee0fQBYJ7q7TPZJy7Bz/XGkLwfOd5DGNf72+unvYGrVqZnaTC7DYCDS/YSKZrpGFGHGAme13338cZZmWbe3/ZOtJNtblTgtk+M4hnJ+KtBMSbEvqa7Im6GigVShhlc0VE3FKx9i6kflssYHXbhSv6yfLVTWrpsPVso/cOBUDWj3BWEJkvwHxOyj9FQMAAA==" autocomplete="off" />
</form>
You don't need to call a list of DataModel when using ui:repeat :
<ui:repeat var="category" value="#{categoriesBean.categories}">
<li><h:outputText value="#{category.name}">
</h:outputText>
</li>
</ui:repeat>
Then when you'll call a service it will be most of the time be database interactions where you inject a service in your bean. For that you should use the #PostConstruct attribute (which is not needed in your case).
#ManagedBean
#RequestScoped
public class CategoriesBean {
// this is not needed but that's how you'd get from db.
//#Inject
//private MyService service;
private List<Category> categories;
// getters and setters
#PostConstruct // in your case this is not needed but it is if you use injection
public void init() {
categories = yourService.getCategories(); // this is not needed.
//instead you can add it like this.
categories = new ArrayList<Category>();
categories.add(1, "blabla");
}
}

How to maintain a list of objects in Java Server Faces 2

I have a JSF2 application that should show a page where a number os items must be added in a list. The user wants to add those items, set some properties of them and finally persist them all together, in a single save operation.
The domain object that should be handled by this page looks like this:
public class Item {
private long id;
private String name;
private Item previous;
public Item() { }
public Item(Item previousItem) {
this.previous = previousItem;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Item getPrevious() {
return previous;
}
}
The ItemBean class looks like this:
#ManagedBean
public class ItemBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
if(items.size()==0) {
items.add(new Item()); // adding the first item
}
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(Item previousItem) {
Item newItem = new Item(previousItem);
items.add(newItem);
}
public void save() {
...
}
}
The view is a xhtml file that looks like this:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="/templates/layout.xhtml">
<ui:define name="content">
<h2>Items</h2>
<fieldset>
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{itemBean.addItem(item)}">Add</h:commandLink>
</div>
</ui:repeat>
</fieldset>
<div class="options">
<h:commandButton action="#{itemBean.save}" value="Save"/>
<div class="clear border-bottom"></div>
</div>
</ui:define>
</ui:composition>
</body>
</html>
Notice that in order to add a new item, the current one must be sent to satisfy business rules.
The problem is that I can add a second item with no problema, but when I click in the Add link next to the second item, the page is rerendered with one single item, just like it was in the beggining.
Unfortunatelly, I can't see what's missing to make it work, even after reading a lot of posts, pages and some book chapters.
Update 1
I was asked about the kind of scope used with this bean. It´s de default scope (#RequestScoped). I was trying to avoid using #SessionScoped for the sake of scalability, but in this particular case, I´m not sure I have a choice. Anyone with more experience could give me tip?
What is the scope of your ManagedBean ?
Since you didn't post any persistence code, I suppose the items List only exists througout your Bean's life. This means that if your Bean is #ViewScoped or #RequestScoped, your items cease to exist after you submit your form.
You need use an ajax component, something like:
<fieldset id="list">
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{cargoBean.addItem(item)}">
<f:ajax render="list" />
Add
</h:commandLink>
</div>
</ui:repeat>
</fieldset>
I see no form in your xhtml page like :
<h:form>
<ui:repeat>
<h:inputBlabla/>
</ui:repeat>
</h:form>
A form is needed while using h:input fields.

JSF 2 : Status-Description selectonemenu

I have 2 selectonemenu elements, one that contains the status of the request, and the other contains a description of that status.
Im trying to implement it as follows :
I have a class called status that has 2 fields : status & description.
the selectonemenu would be :
<h:outputText id="requestStatusH" value="Status : " />
<h:selectOneMenu id="statusDD" value="#{exApp.status}">
<f:selectItems value="#{exApp.statusList}" />
</h:selectOneMenu>
and my exApp bean would be :
private RequestStatus status;
private List<RequestStatus> statusList;
//Getters + Setters
when i select a status in one selectonemenu i want the corresponding description to appear in another disabled selectonemenu.
The problem is that im not able to even get the selected value in to the backing bean variables.
after i submit the page, nothing is happening.
I tried to look into the stackoverflow selectonemenu guide, and i couldnt find anything about converters.
any help would be highly appreciated.
Edit :
My RequestStatus code :
public class RequestStatus implements Serializable {
public RequestStatus(String status, String description) {
this.status = status;
Description = description;
}
private String status;
private String Description;
//Getters + Setters
my form :
<h:form>
<p:commandLink id="saveChanges" value="Save Changes" actionListener=
"#{exApp.saveRespond()}"> </p:commandLink>
<h:outputText id="requestStatusH" value="Status : " />
<h:selectOneMenu id="statusDD" value="#{exApp.status}">
<f:selectItems value="#{exApp.statusList}" />
</h:selectOneMenu>
</h:form>
RequestStatus Class is not a backing bean, its a POJO that is used as a field in the RequestScope exApp backing bean.
my page is using Form. and when i submit my form NOTHING happens.

<p:selectOneMenu> selected value always null

My goal is to get the selected value of type Sistema, so I can update a datatable and another SelectOneMenu.
Whenever a value is selected the ajax tag behaves correctly, and calls configura(), however my sistemaSelecionado (wich is an Object in Bean)always return as null to my Backing Bean.
The converter is working fine in another page with the same class Sistema. But it doesn't fire on this specific page.
This is the xhtml page
<div>
<p:outputLabel title="Sistema"></p:outputLabel>
</div>
<div>
<p:selectOneMenu id="selectOneMenu"
value="#{permissaoListBean.sistemaSelecionado}"
converter="entityConverter">
<p:ajax event="change" listener="#{permissaoListBean.configura}"
update="selectOneMenuGrupo,secoes"></p:ajax>
<f:selectItem itemLabel="Selecione" itemValue="" />
<f:selectItems value="#{permissaoListBean.listaSistema}"
var="sistema" itemLabel="#{sistema.nome}" itemValue="#{sistema}">
</f:selectItems>
</p:selectOneMenu>
</div>
Here is my Backing Bean
#Component("permissaoListBean")
#Scope("session")
public class PermissaoListBean {
private List<Sistema> listaSistema = new ArrayList<Sistema>();
//Service das entidades
#Autowired
private SistemaService sistema;
#Autowired
private GrupoService grupo;
#Autowired
private SecaoService secao;
//Objetos da view
private Sistema sistemaSelecionado;
private Grupo grupoSelecionado;
private List<Secao> secaoSelecionada = new ArrayList<Secao>();
private LazyDataModel<Secao> modelo ;
public void populaSistema(){
listaSistema = sistema.findAll();
}
public void configura(){
populaGrupo();
populaSecao();
}
public void populaGrupo(){
setListaGrupo(grupo.findBySistema(sistemaSelecionado));
}
//dataTable lazyLoad code
//end of lazyload
public List<Sistema> getListaSistema() {
setListaSistema(sistema.findAll());
return listaSistema;
}
public void setListaSistema(List<Sistema> listaSistema) {
this.listaSistema = listaSistema;
}
//getters and setters

<h:inputText> howto execute bean method on blur?

I have <h:inputText> on form and what I need is to execute some method from backing bean on BLUR event:
public void test()
{
System.out.print("HELLO!");
}
Can you help me?
You can use <f:ajax>
<h:form>
<h:inputText value="#{managedBean.val}" >
<f:ajax event="blur" render="result" listener="#{managedBean.test}"/>
</h:inputText>
</h:form>
#ManagedBean(name = "managedBean")
public class Bean {
private String val; // getter and setter
...
public void test() {
System.out.print("HELLO!");
}
}
Alternative :
If you are using richfaces then you can use a4j:jsFunction
See Also
JSF2: Ajax in JSF – using f:ajax tag
How-to-update-a-value-displayed-in-the-page-without-refreshing

Categories