ViewScoped Bean get rebuild on commandLink - jsf

I am building a CRUD app with a dashboard in which the user should be able to partially reload a widget. This is what I got:
<f:metadata>
<f:viewParam name="customerUuid" value="#
{dashboardManagedBean.customerUuid}" />
<f:event type="preRenderView" listener="#{dashboardManagedBean.init}" />
</f:metadata>
<f:view>
<h:body>
<h:form>
<p:panelGrid>
<p:row>
<p:column>
<p:panelGrid columns="4" styleClass="ui-noborder"
style="float:right;">
<p:outputLabel for="dateFrom" value="From:">
</p:outputLabel>
<p:calendar id="dateFrom" value="#
{dashboardManagedBean.statisticsRequest.dateFrom}"
pattern="dd.MM.yyyy HH:mm:ss" locale="de" readonlyInput="false"
timeInput="true" mode="popup"/>
<p:outputLabel for="dateTo" value="Till:">
</p:outputLabel>
<p:calendar id="dateTo" value="#
{dashboardManagedBean.statisticsRequest.dateTo}" pattern="dd.MM.yyyy
HH:mm:ss" locale="de" readonlyInput="false" timeInput="true"
mode="popup"/>
</p:panelGrid>
</p:column>
</p:row>
<p:row>
<p:column colspan="3">
<p:panel id="telemetry" header="Telemetrie"
style="width: 100%" collapsed="true" toggleable="true">
<f:facet name="actions">
<p:commandLink
actionListener="#
{dashboardManagedBean.loadData}"
styleClass="ui-panel-titlebar-icon
ui-corner-all ui-state-default"><h:outputText
styleClass="fa fa-refresh"/>
</p:commandLink>
</f:facet>
</p:panel>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</h:body>
</f:view>
And the bean looks like this:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "dashboardManagedBean")
#ViewScoped #Getter #Setter
public class DashboardManagedBean implements Serializable {
private Customer customer;
private StatisticsRequest statisticsRequest;
private String customerUuid;
public DashboardManagedBean() {
this.customer = new Customer();
this.statisticsRequest = new StatisticsRequest();
}
public void init() {
loadCustomer();
loadData();
}
public void loadData(){
// load the customer data by using his the statisticsRequest
}
public void loadCustomer(){
// load the customer
}
}
The StatisticsRequest Class is just a wrapper for the request data:
#Getter #Setter
public class StatisticsRequest {
private Customer customer;
private Date dateFrom;
private Date dateTo;
public StatisticsRequest(){
java.util.Date da = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(da);
cal.add(Calendar.MONTH, -4);
this.dateFrom = cal.getTime();
this.dateTo = new Date();
}
}
I put this into the constructor of the StatisticsRequest so that I get a reasonable default value when loading the page. However the constructor of the viewscoped bean is called everytime I click on the reload commandLink the date I picked in the calendar is removed and the StatisticsRequest contains the default value again.
Why is this happening?

Related

Add item into Primefaces table

I want to add item into Primefaces table when I create new item. I managed to create this code:
<h:form id="new_item_button">
<p:commandButton id="ajax" value="New Sensor" styleClass="ui-priority-primary" onclick="PF('dlg').show();" type="button"/>
</h:form>
<h:form id="new_sensor">
<p:dialog header="New Sensor" widgetVar="dlg" focus="name" modal="true" showEffect="fade">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="name" value="Name" />
<p:inputText id="name" label="name" value="#{newSensor.sensor.name}" />
.............................
</h:panelGrid>
<f:facet name="footer">
<p:commandButton id="ajax" value="Create Sensor" actionListener="#{newSensor.saveRecord()}" update=":new_sensor"/>
</f:facet>
</p:dialog>
</h:form>
<h:form id="form">
<p:dataTable id="tbl" var="sensor" value="#{sensors.systemSensors}"
.......
paginator="true" rows="12"
rowKey="#{sensor.model}">
<p:column headerText="Name" sortBy="#{sensor.name}" style="text-align: center">
<h:outputText value="#{sensor.name}" />
</p:column>
...................
</p:column>
</p:dataTable>
Beans:
#Named
#RequestScoped
public class Sensors implements Serializable
{
private List<SensorObj> sensors;
#PostConstruct
public void init()
{
sensors = generateSensors();
}
public List<SensorObj> getSystemSensors()
{
return sensors;
}
private List<SensorObj> generateSensors()
{
List list = new ArrayList();
SensorObj obj1 = new SensorObj("Sensor 1", "SBS0212", "Online", true, null);
list.add(obj1);
return list;
}
}
#Named
#RequestScoped
public class NewSensor implements Serializable
{
private SensorObj sensor = new SensorObj();
public SensorObj getSensor()
{
return sensor;
}
public void setSensor(SensorObj sensor)
{
this.sensor = sensor;
}
public void saveRecord(){
.....
}
}
When I submit the dialog with the new sensor I want to update the table. How I can implement this?
Should I use one managed bean for listing the content and adding new items or as it is it's better to use two?

Action empties the selectonemenu

I have a simple form, with some input and a selectonemenu:
<h:panelGroup id="Client">
<h:form id="formClient">
<p:panelGrid columns="3" layout="grid"
columnClasses="labelWidth, ui-grid-col-3">
<p:outputLabel value="CIN:" for="txtCin" />
<h:panelGrid columns="2">
<p:inputText value="#{clientBean.client.identifiant}" id="txtCin"></p:inputText>
<p:commandButton value="Search" process="#parent"
styleClass="orangeButton" update="formClient"
style="margin-top: -10px;" action="#{clientBean.rechercher()}"></p:commandButton>
</h:panelGrid>
<p:message for="txtCin" />
<p:outputLabel value="Nom:" for="txtNom" />
<p:inputText id="txtNom" styleClass="form-control"
value="#{clientBean.client.nomClient}" required="true"
requiredMessage="Le nom est obligatoire" />
<p:message for="txtNom" />
<p:outputLabel value="Type de voie:" for="txtVoie" />
<p:selectOneMenu styleClass="form-control"
value="#{clientBean.client.typeVoie}" id="txtVoie">
<f:selectItem itemLabel="Selectionnez voie..." itemValue="" />
<f:selectItems value="#{clientBean.typeVoies}" var="typeVoie" itemLabel="#{typeVoie.libelle}" itemValue="#{typeVoie}" />
</p:selectOneMenu>
<p:message for="txtVoie" />
<p:outputPanel></p:outputPanel>
<p:outputPanel>
<p:commandButton value="Annuler" update="formClient"
styleClass="redButton" process="#this"
actionListener="#{clientBean.cancel()}" />
<p:commandButton ajax="false" value="Suivant"
styleClass="greenButton" action="Devis?faces-redirect=true"></p:commandButton>
</p:outputPanel>
</p:panelGrid>
</h:form>
</h:panelGroup>
As you see here i have some fields that are a required, and a button to cancel (empties) the form:
#ManagedBean(name = "clientBean")
#SessionScoped
public class ClientBean implements Serializable {
#EJB
private IClientDAO clientDAO;
#EJB
private ITypeVoieDAO typeVoieDAO;
private List<TypeVoie> typeVoies;
private static final long serialVersionUID = -3324864097586374969L;
private Client client = new Client();
#PostConstruct
public void init(){
typeVoies = typeVoieDAO.findAll();
}
public Client getClient() {
return client;
}
public void setClient(Client client) {
this.client = client;
}
public void rechercher(){
if(client != null && client.getIdentifiant() != null){
System.out.println(client.getIdentifiant());
client = clientDAO.findByIdentifiant(client.getIdentifiant());
if(client == null){
cancel();
}
}
}
public void cancel(){
client = new Client();
System.out.println(typeVoies);
}
public String navigateToClientPage(){
rechercher();
return "client?faces-redirect=true";
}
public List<TypeVoie> getTypeVoies() {
return typeVoies;
}
public void setTypeVoies(List<TypeVoie> typeVoies) {
this.typeVoies = typeVoies;
}
}
At the page loads, the selectonemenu loads perfectly, but when i click cancel, the selectonemenu gets emptied, even when i "search" for a client, and updates the form, all the other fields are filled properly, but the selectonemenu gets completely empty.
Using JSF 2.1 and primefaces 6.0
UPDATE:
Added a converter, but nothing change ...
Make sure you dont empty typeVoies list at some point on your backingbean. And if you can share your full java class, you might get more accurate help.

p:inputTextarea returns empty string

I have a p:inputTextarea and I need the value of it while processing the form. It turned out that every time I submit the form I get all the values except the one from the textarea. #{xyzUI.description} is a String object with regular getters and setters.
<ui:composition>
<h:form id="form1">
<p:panel rendered="...">
<p:panel id="formPanel">
<p:panelGrid columns="2" cellpadding="5">
<!-- other form elements -->
<p:outputLabel>Description:</p:outputLabel>
<p:inputTextarea value="#{xyzUI.description}" style="width: 350px;" counter="display" counterTemplate="{0} characters remaining" maxlength="2000" autoResize="true" rows="4" />
<h:panelGroup />
<h:outputText id="display" />
</p:panelGrid>
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
</p:panel>
</p:panel>
</h:form>
<ui:composition>
In my backing bean the value is always "". I don't know what's wrong.
public void submitForm()
{
...
tmp.setDescription(description); // String is always "" while debugging
myList.add(tmp);
RequestContext.getCurrentInstance().update("content");
}
I ran your code locally and discovered the issue. In the command button, remove the p:ajax call.
PrimeFaces command buttons are ajax enabled by default.
So change this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" ajax="true" value="Apply" >
<p:ajax update="formPanel"></p:ajax>
</p:commandButton>
To this:
<p:commandButton rendered="#{not xyzUI.noChange}" action="#{xyzUI.submitForm}" update="formPanel" value="Apply" />
My backing bean for reference
#ManagedBean
#ViewScoped
public class xyzUI implements Serializable{
private static final long serialVersionUID = 6259024062406526022L;
private String description;
private boolean noChange = false;
public xyzUI(){
}
public void submitForm(){
System.out.println(description);
}
public boolean isNoChange() {
return noChange;
}
public void setNoChange(boolean noChange) {
this.noChange = noChange;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

PrimeFaces - Unable to delete rows in datatable

I am trying to do a basic add and delete db operation using primeface datatable. Add is working fine but cannot get the delete working. When I click on the delete button the delete function is not called.
<h:body>
<h:form>
<p:panel id="toppanel" closable="true" toggleable="true" >
<f:facet name="Store">
<p:outputLabel value="Header" />
</f:facet>
<f:facet name="#Copyright" >
<p:outputLabel value="footer" />
</f:facet>
<p align="left" >
<p:inputText value="#{salesPerson.item.itemId}" id="itemid" >
<f:passThroughAttribute name="placeholder" value="ID"/>
</p:inputText>
<p:inputText value="#{salesPerson.item.itemTitle}" >
<f:passThroughAttribute name="placeholder" value="TITLE"/>
</p:inputText>
<p:inputText value="#{salesPerson.item.itemDesc}" >
<f:passThroughAttribute name="placeholder" value="DESCRIPTION"/>
</p:inputText>
<p:inputText value="#{salesPerson.item.price}" >
<f:passThroughAttribute name="placeholder" value="PRICE"/>
</p:inputText>
</p>
<p align="right" >
<p:commandButton process="#form" id="Create" value="Create" update="out" actionListener="#{salesPerson.addItem()}" />
</p>
<p:dataTable id="out" var="item" value="#{salesPerson.items}" rowKey="#{item.itemId}" selection="#{salesPerson.selectedItems}" >
<p:column selectionMode="multiple" width="1%"/>
<p:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet >
<h:outputText value="#{item.itemId}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="TITLE" />
</f:facet >
<h:outputText value="#{item.itemTitle}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="DESCRIPTION" />
</f:facet >
<h:outputText value="#{item.itemDesc}" />
</p:column>
<p:column>
<f:facet name="header">
<h:outputText value="PRICE" />
</f:facet >
<h:outputText value="#{item.price}" />
</p:column>
</p:dataTable>
<p align="right" >
<p:commandButton process="#form" id="delete" value="Delete" update="out" actionListener="#{salesPerson.deleteItem(items)}" />
</p>
</p:panel>
</h:form>
</h:body>
</html>
SalesPerson Bean
This is the controller backing bean
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.parthi.controller;
import javax.inject.Inject;
import com.parthi.model.Item;
import com.parthi.backing.ShoppingBean;
import com.parthi.service.StoreKeeper;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import javax.ejb.EJB;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#RequestScoped
#Named
public class SalesPerson implements Serializable{
#Inject
private Item item;
private List<Item> items = new LinkedList<>();
private List<Item> selectedItems = new LinkedList<>();
#EJB
private StoreKeeper storeKeeper;
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
public List<Item> getSelectedItems() {
System.out.println("Number of items getselected" +selectedItems.size());
return selectedItems;
}
public void setSelectedItems(List<Item> selectedItems) {
System.out.println("Number of items setselected" +selectedItems.size());
this.selectedItems = selectedItems;
}
public void addItem(){
storeKeeper.addItem(item);
// System.out.println("Printing add item");
}
public List<Item> getAllItems() {
// System.out.println("Getting all SalesPerson-items");
items = storeKeeper.getAllItems();
return items;
}
public void deleteItem(List<Item> items){
System.out.println("Reached SalesPerson.deleteItem");
int i =0;
while(i <= items.size()){
storeKeeper.deleteItem(items.get(i));
i++;
System.out.println("deleting..." + items.get(i));
}
}
public List<Item> getItems() {
getAllItems();
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
Service EJB
Service is a stateless session bean which perform CRUD operations
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package com.parthi.service;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import com.parthi.model.Customer;
import com.parthi.model.Item;
#Stateless
public class StoreKeeper {
#PersistenceContext
private EntityManager em;
public List<Item> getAllItems(){
System.out.println("Getting all StoreKeeper-item");
return em.createQuery("FROM Item p", Item.class).getResultList();
}
public void addItem(Item item){
System.out.println("Printing all StoreKeeper add item");
em.persist(item);
}
public void deleteItem(Item item){
em.merge(item);
em.remove(item);
}
}

How to pass parameters between two pages (from p:commandLink with redirect=true and view scoped beans)?

I am trying to pass a parameter (a user's id from a datatable) from one page to the next where I am using it (showing the user's details). The problem is that I can not get it. What am I missing? What am I doing wrong? I am using PrimeFaces 5 and JSF 2.2 (also Hibernate 4). Is there any way that I can have the parameter #PostConstruct so that I can load the user's details immediately?
The first page with the datable
<h:form id="manageUserForm" prependId="false">
<p:growl id="messages" showDetail="true" life="20000"/>
<p:dataTable id="usersTable" var="user" value="#{manageUsers.users}">
<f:facet name="header">
#{pvtmsg.registeredUsers}
</f:facet>
<p:column headerText="ID">
<h:outputText value="#{user.id}" />
</p:column>
<p:column headerText="#{pvtmsg.username}">
<h:outputText value="#{user.username}" />
</p:column>
<p:column headerText="#{pvtmsg.firstname}">
<h:outputText value="#{user.firstname}" />
</p:column>
<p:column headerText="#{pvtmsg.lastname}">
<h:outputText value="#{user.lastname}" />
</p:column>
<p:column headerText="#{pvtmsg.email}">
<h:outputText value="#{user.email}" />
</p:column>
<p:column headerText="#{pvtmsg.status}">
<h:outputText value="#{user.enabled ? pvtmsg.enabled : pvtmsg.disabled}" />
</p:column>
<p:column style="width:32px;text-align: center">
<p:commandLink action="editUser.xhtml?faces-redirect=true">
<f:setPropertyActionListener value="#{user.id}" target="#{manageUsers.selectedUser}" />
<f:param name="userId" value="#{manageUsers.selectedUser}" />
</p:commandLink>
</p:column>
</p:dataTable>
</h:form>
Its backing bean
package beans;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import models.User;
import utils.PropertyHelper;
#Named(value = "manageUsers")
#ViewScoped
public class ManageUsers implements Serializable {
private static final long serialVersionUID = 954672295622776147L;
private List<User> users = null;
private String selectedUser = null;
public ManageUsers() {
try {
PropertyHelper helper = new PropertyHelper();
users = helper.getUsers();
} catch (Exception ex) {
Logger.getLogger(ManageUsers.class.getName()).log(Level.SEVERE, null, ex);
}
}
public List<User> getUsers() {
return users;
}
public String getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(String selectedUser) {
this.selectedUser = selectedUser;
}
}
The second page
<f:metadata>
<f:viewParam name="userId" value="#{editUserBean.userId}" />
</f:metadata>
<h:form id="editUserForm" prependId="false">
<p:growl id="messages" showDetail="true" life="20000"/>
<!--nothing yet-->
</h:form>
Its backing bean
package beans;
import java.io.Serializable;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named(value = "editUserBean")
#ViewScoped
public class EditUserBean implements Serializable {
private static final long serialVersionUID = 543216875622776147L;
private String userId;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
}
Your commandLink doesn't make sense here. Typically when you want to navigate with a commandLink, you should do a redirect in your backing bean.
If you want to navigate using outcome, then something like this should work for you:
<h:link outcome="editUser.xhtml">
<f:param name="userId" value="#{user.id}" />
</h:link>
So I found my solution here http://www.oracle.com/technetwork/articles/java/jsf22-1377252.html and, after some time, the last piece that I needed here here http://www.coderanch.com/t/625319/JSF/java/working-viewParam
Your f:viewParams won't be available during the #PostConstruct method call. You should assign a f:viewAction, since you are using JSF 2.2, to handle business processing on GET parameters.
<f:metadata>
<f:viewParam name="userId" value="#{editUserBean.userId}" />
<f:viewAction action="#{editUserBean.processUserId}"/>
</f:metadata>
See also:
Read this if using JSF older than 2.2
JSF bean: call #PostConstruct function after ViewParam is set

Resources