Dynamic Textfield In JSF 2.0 - jsf

hey I am using the following code to create the number of text fields as the user wants
<h:form>
<p>Number Of News <h:inputText value="#{news.noOfFields}" /></p>
<ui:repeat value="#{news.values}" var="item">
<hr/>
News #{item.no}
<h:inputText value="#{item.news}" /><br/>
</ui:repeat>
<hr/>
<h:commandButton styleClass="btn btn-blue" action="#{news.submit}" value="Save" />
</h:form>
The managed bean news has a class News as
#ManagedBean
#SessionScoped
public class News
{
private String noOfFields;
private List<NewsVO> values;
public News()
{
this.values = new ArrayList<NewsVO>();
}
public String submit() {
for(NewsVO newsVO : this.values)
{
System.out.println(newsVO.getNews());
System.out.println(newsVO.getNo());
}
return null;
// save values in database
}
public String getNoOfFields() {
return noOfFields;
}
public List<NewsVO> getValues() {
return values;
}
public void setValues(List<NewsVO> values) {
this.values = values;
}
public void setNoOfFields(String noOfFields) {
this.values = new ArrayList<NewsVO>();
try {
for(int i=0;i<Integer.valueOf(noOfFields);i++)
{
NewsVO newsVO = new NewsVO();
newsVO.setNo(i+1);
this.values.add(newsVO);
}
this.noOfFields = noOfFields;
}
catch(NumberFormatException ex) {
/*values = new String[1];*/
noOfFields = "1";
}
}
}
The NewsVO is just a javaBean class as follows
public class NewsVO
{
public int no;
public String news;
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getNews() {
return news;
}
public void setNews(String news) {
this.news = news;
}
}
The problem is the values inside the input Text doesn't get reflected on pressing the save button. It gives me null, even though, I have written something inside all the textfields.
<h:inputText value="#{item.news}" />

Everytime you push the submit button, all setters in the bean are called (including setNoOfFields()). In this setter you are resetting your list, that's why you loose your values. Since you only need to modify your list if there is a size change, here is a simple way doing it :
#ManagedBean
#SessionScoped
public class News
{
private int noOfFields;
private List<NewsVO> values;
public News()
{
this.values = new ArrayList<NewsVO>();
}
public String submit()
{
for(NewsVO newsVO : this.values)
{
System.out.println(newsVO.getNews());
System.out.println(newsVO.getNo());
}
return null;
// save values in database
}
public int getNoOfFields()
{
return noOfFields;
}
public List<NewsVO> getValues()
{
return values;
}
public void setValues(List<NewsVO> values)
{
this.values = values;
}
public void setNoOfFields(int noOfFields)
{
if(noOfFields < this.noOfFields)
{
for(int i = this.noOfFields - 1;i >= noOfFields;i--)
{
getValues().remove(i);
}
}
else if(noOfFields > this.noOfFields)
{
for(int i = this.noOfFields;i < noOfFields;i++)
{
NewsVO newsVO = new NewsVO();
newsVO.setNo(i+1);
getValues().add(newsVO);
}
}
}
}
Note : I've also changed your noOfFields getter/setter for simple int, JSF will do the conversion for you.

Related

Pass changed value from inputText to bean

I'm trying to pass the changed value of the variable to a bean method:
<h:panelGroup rendered="#{! empty gradesBean.getAllGrades()}">
<h:dataTable value="#{gradesBean.getAllGrades()}" var="g">
<h:column>
<f:facet name="header">#{msg['outputSubject']}</f:facet>
<h:inputText value="#{g.subject}" onchange="#{g.subject}" />
</h:column>
<h:column>
<f:facet name="header">#{msg['outputGrade']}</f:facet>
<h:inputText value="#{g.mark}" onchange="#{g.mark}"/>
</h:column>
<h:column>
<h:form>
<h:commandButton value="#{msg['actionSave']}" action="#{gradesBean.edit(g)}" />
</h:form>
</h:column>
</h:dataTable>
(.........)
</h:panelGroup>
I want the changes of the user he does in the inputText on g.subject and g.mark to be passed to gradesBean.edit(g). When I try to do that somehow the same values of the original values of the both variables are passed. There are getter and setter methods in the respective object
#Named
#ViewScoped
public class GradesBean extends AbstractBean implements Serializable {
private static final long serialVersionUID = 320401008216711886L;
private static final String NO_GRADES_PRESENT = "keine Noten eingetragen";
private static final Logger loggerLogger.getLogger(GradesBean.class);
#Inject
private transient GradeDAO gradeDAO;
#Inject
private UserDAO userDAO;
private Grade grade;
private List<Grade> allGrades;
#PostConstruct
public void init() {
if (!isLoggedIn()) {
return;
}
grade = new Grade();
allGrades = getSession().getUser().getGrades();
}
public Grade getGrade() {
return grade;
}
public List<Grade> getAllGrades() {
return allGrades;
}
public String getGradeAverage() {
final List<BigDecimal> theDecimals = new ArrayList<>(allGrades.size());
for (final Grade g : allGrades) {
theDecimals.add(g.getMark());
}
final Configuration config = Configuration.getDefault();
final int scale = config.getScale();
final RoundingMode roundingMode = config.getRoundingMode();
try {
final BigDecimal average = de.unibremen.st.gradelog.businesslogic.Math
.average(theDecimals, scale, roundingMode);
return average.stripTrailingZeros().toPlainString();
} catch (final ArithmeticException e) {
logger.debug(
"Calculation of grade average has been called without any grades.", e);
return NO_GRADES_PRESENT;
}
}
public String getGradeMedian() {
final List<BigDecimal> theDecimals = new ArrayList<>(allGrades.size());
for (final Grade g : allGrades) {
theDecimals.add(g.getMark());
}
try {
final BigDecimal median = de.unibremen.st.gradelog.businesslogic.Math
.median(theDecimals);
return median.stripTrailingZeros().toPlainString();
} catch (final ArithmeticException e) {
logger.debug(
"Calculation of grades median has been called without any grades.", e);
return NO_GRADES_PRESENT;
}
}
public String save() {
if (!isLoggedIn()) {
return null;
}
final User user = getSession().getUser();
grade.setUser(user);
user.addGrade(grade);
gradeDAO.save(grade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
public String edit() {
if (!isLoggedIn()) {
return null;
}
assertNotNull(grade);
final User user = getSession().getUser();
gradeDAO.update(grade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
public String remove(final Grade theGrade) {
if (!isLoggedIn()) {
return null;
}
assertNotNull(theGrade);
final User user = getSession().getUser();
user.removeGrade(theGrade);
gradeDAO.remove(theGrade);
try {
userDAO.update(user);
} catch (final DuplicateUniqueFieldException e) {
throw new UnexpectedUniqueViolationException(e);
}
init();
return null;
}
}`
g.mark and g.subject will already call the corresponding setters on your backing bean class (I assume that public setters getMark() and getSubject() exist).
Since action="#{gradesBean.edit(g)}" is resolved at the server (when the page is first displayed), it will have the original values , not the changed values. Anyway , to see the changed values you can use ajax (f:ajax tag and the corresponding listener attribute should be set). But you don't have to do this. Simply change your handler to
action="#{gradesBean.edit()}" //no argument
and get the latest values from your bean class instance.
I could be more specific if you want.

Storing a http session attribute in database

How can I pass an injected http session attribute (see below), along with other values (informe by the user) and save them using JPA?
The session attribute is correctly displayed and injected, but I need to pass it using the selected to be stored in the database (actually, it passess null).
The JSF:
<p:outputLabel value="UserID (the sessionAttribute):" for="userID" />
<p:inputText id="userID" value="#{userBean.myUser.xChave}" title="userID" />
<p:outputLabel value="Type the Reason:" for="reason" />
<p:inputText id="reason" value="#{viagensController.selected.reason}" />
<!-- updated (just the call to the action method: -->
<p:commandButton actionListener="#{viagensController.saveNew}" value="#{viagensBundle.Save}" update="display,:ViagensListForm:datalist,:growl" oncomplete="handleSubmit(xhr,status,args,ViagensCreateDialog);" />
The bean:
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.inject.Named;
#Named(value = "userBean")
#SessionScoped
public class UserBean implements Serializable {
private bean_login myUser;
public bean_login getMyUser() {
return myUser;
}
public void setMyUser(bean_login myUser) {
this.myUser = myUser;
}
#PostConstruct
public void init() {
String uid = FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("xChave").toString();
myUser = new bean_login();
myUser.setxChave(uid);
System.out.print("from init:" + myUser.toString());
}
}
The AbstractFacade:
public abstract class AbstractFacade<T> {
private Class<T> entityClass;
public AbstractFacade(Class<T> entityClass) {
this.entityClass = entityClass;
}
protected abstract EntityManager getEntityManager();
public void create(T entity) {
getEntityManager().persist(entity);
}
public void edit(T entity) {
getEntityManager().merge(entity);
}
public void remove(T entity) {
getEntityManager().remove(getEntityManager().merge(entity));
}
public T find(Object id) {{ /*impl. ommited*/ }
public List<T> findAll() {{ /*impl. ommited*/ }
public List<T> findRange(int[] range) { /*impl. ommited*/ }
public int count() { /*impl. ommited*/ }
}
The AbstractController (for the selected in JSF above and other methods):
public abstract class AbstractController<T> {
#Inject
private AbstractFacade<T> ejbFacade;
private Class<T> itemClass;
private T selected;
private Collection<T> items;
private enum PersistAction {
CREATE,
DELETE,
UPDATE
}
public AbstractController() {
}
public AbstractController(Class<T> itemClass) {
this.itemClass = itemClass;
}
public T getSelected() {
return selected;
}
// Pass in the currently selected item
public void setSelected(T selected) {
this.selected = selected;
}
protected void setEmbeddableKeys() {
}
protected void initializeEmbeddableKey() {
}
public Collection<T> getItems() {
if (items == null) {
items = this.ejbFacade.findAll();
}
return items;
}
// Pass in collection of items
public void setItems(Collection<T> items) {
this.items = items;
}
// Apply changes to an existing item to the data layer.
public void save(ActionEvent event) {
String msg = ResourceBundle.getBundle("/viagensBundle").getString(itemClass.getSimpleName() + "Updated");
persist(PersistAction.UPDATE, msg);
}
// Store a new item in the data layer.
public void saveNew(ActionEvent event) {
String msg = ResourceBundle.getBundle("/viagensBundle").getString(itemClass.getSimpleName() + "Created");
persist(PersistAction.CREATE, msg);
if (!isValidationFailed()) {
items = null; // Invalidate list of items to trigger re-query.
}
}
public void delete(ActionEvent event) {/*implementations ommited*/ }
private void persist(PersistAction persistAction, String successMessage) {
if (selected != null) {
this.setEmbeddableKeys();
try {
if (persistAction != PersistAction.DELETE) {
this.ejbFacade.edit(selected);
} else {
this.ejbFacade.remove(selected);
}
JsfUtil.addSuccessMessage(successMessage);
} catch (EJBException ex) {
String msg = "";
Throwable cause = JsfUtil.getRootCause(ex.getCause());
if (cause != null) {
if (cause instanceof ConstraintViolationException) {
ConstraintViolationException excp = (ConstraintViolationException) cause;
for (ConstraintViolation s : excp.getConstraintViolations()) {
JsfUtil.addErrorMessage(s.getMessage());
}
} else {
msg = cause.getLocalizedMessage();
if (msg.length() > 0) {
JsfUtil.addErrorMessage(msg);
} else {
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
}
}
}
} catch (Exception ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, ResourceBundle.getBundle("/viagensBundle").getString("PersistenceErrorOccured"));
}
}
}
// Creates a new instance of an underlying entity and assigns it to Selected property.
public T prepareCreate(ActionEvent event) {
T newItem;
try {
newItem = itemClass.newInstance();
this.selected = newItem;
initializeEmbeddableKey();
return newItem;
} catch (InstantiationException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
}
return null;
}
// Inform the user interface whether any validation error exist on a page.
public boolean isValidationFailed() {
return JsfUtil.isValidationFailed();
}
// Retrieve all messages as a String to be displayed on the page.
public String getComponentMessages(String clientComponent, String defaultMessage) {
return JsfUtil.getComponentMessages(clientComponent, defaultMessage);
}
}
Thanks in advance.
updated:
The ViagensController:
#Named(value = "viagensController")
#ViewScoped
public class ViagensController extends AbstractController<Viagens> implements Serializable {
//generics:passing JPA Entity class, where the 'reason' in JSF is defined
public ViagensController() {
super(Viagens.class);
}
}
Need to override the save method passing the injected http session value :
#ManagedBean(name = "riscosController")
#ViewScoped
public class RiscosController extends AbstractController<Riscos> {
#EJB
private RiscosFacade ejbFacade;
#Inject
#SessionChave
private String iSessionChave;
private String sessionChave;
private UorPosController matriculaController;
private UorPosController informanteController;
public String getSessionChave(String chave) {
if (sessionChave.isEmpty()) {
sessionChave = iSessionChave;
}
return sessionChave;
}
public void setSessionChave(String sessionChave) {
this.sessionChave = sessionChave;
}
#PostConstruct
#Override
public void init() {
super.setFacade(ejbFacade);
FacesContext context = FacesContext.getCurrentInstance();
matriculaController = context.getApplication().evaluateExpressionGet(context, "#{uorPosController}", UorPosController.class);
informanteController = context.getApplication().evaluateExpressionGet(context, "#{uorPosController}", UorPosController.class);
sessionChave = "";
}
#Override
public void saveNew(ActionEvent event) {
this.getSelected().setObs(this.getSessionChave(sessionChave));
super.saveNew(event);
}
}

Primefaces p:orderList java backing list does not update

I am currently implementing a orderable list using PrimeFaces' component, embedded inside a . I was able to get the list to appear properly with my items. However, when I saved the list and submitted it back to the server, the rearranged items did not get reflected in the backing bean for some reason. Since the Primefaces showcase was able to see the changes, what am I doing wrong?
XHTML Snippet:
<h:form id="confirmDialogForm">
<p:confirmDialog id="arrangeProjDialog" widgetVar="arrangeDlg" width="600"
header="Meeting Order"
appendToBody="true" message="Drag and drop to rearrange meeting order">
<p:orderList id="arrangeProjDialogList"
value="#{adminMeetingListBean.orderProjList}"
converter="#{adminMeetingListBean.rowConverter}"
var="po"
controlsLocation="left"
styleClass="wideList"
itemLabel="#{po.projectTitle}"
itemValue="#{po}"
>
<f:facet name="caption">Proposals</f:facet>
</p:orderList>
<p:commandButton value="Save" ajax="true" process="arrangeProjDialogList #this"
actionListener="#{adminMeetingListBean.updateProposalMeetingOrder}" onclick="arrangeDlg.hide();">
</p:commandButton>
<p:button value="Cancel" onclick="arrangeDlg.hide(); return false;" />
</p:confirmDialog>
</h:form>
Backing Bean:
public void updateProposalMeetingOrder() {
if (selectedMeeting != null) {
orderProjTitles.get(0);
meetingService.updateMeetingProjSequence(orderProjList, selectedMeeting.getMeetingId());
}
}
The List is a list of POJO "ProposalOrderRow" objects. This has the definition:
public class ProposalOrderRow implements Serializable {
private static final long serialVersionUID = -5012155654584965160L;
private int dispSeq;
private int appId;
private int assignmentId;
private String refNo;
private String projectTitle;
public int getDispSeq() {
return dispSeq;
}
public void setDispSeq(int dispSeq) {
this.dispSeq = dispSeq;
}
public int getAppId() {
return appId;
}
public void setAppId(int appId) {
this.appId = appId;
}
public String getRefNo() {
return refNo;
}
public void setRefNo(String refNo) {
this.refNo = refNo;
}
public String getProjectTitle() {
return projectTitle;
}
public void setProjectTitle(String projectTitle) {
this.projectTitle = projectTitle;
}
public int getAssignmentId() {
return assignmentId;
}
public void setAssignmentId(int assignmentId) {
this.assignmentId = assignmentId;
}
}
Converter:
#FacesConverter("proposalOrderRowConverter")
public class ProposalOrderRowConverter implements Converter {
private List<ProposalOrderRow> orderRows;
#Override
public Object getAsObject(FacesContext context, UIComponent component, String newValue) {
if (newValue.isEmpty()) {
return null;
}
for (ProposalOrderRow item : orderRows) {
String refNo = item.getRefNo();
if (refNo.equals(newValue)) {
return item;
}
}
return null;
}
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) {
return "";
}
ProposalOrderRow row = (ProposalOrderRow) value;
String output = row.getRefNo();
return output;
}
public List<ProposalOrderRow> getOrderRows() {
return orderRows;
}
public void setOrderRows(List<ProposalOrderRow> orderRows) {
this.orderRows = orderRows;
}
}
This problem is caused by appendToBody="true" in the confirm dialog. Setting it to false solved the problem.
See link here: link

Catching PrimeFaces's spinner value inside repeat structure

I'm using Primefaces and spinner component. My problem is that the spinner value is not set in the bean, if it's inside an iteration structure. My spinner is inside ui:repeat.
In the end, the problem is how to deal with different form controls mapping to the same property in bean.
<h:form>
<ui:repeat var="item" value="#{myBean.items}">
<p:spinner size="2" min="1" max="50" style="width:75px" value="#{cartBean.quantityToOrder}"/>
<p:commandButton value="Add to cart" action="#{cartBean.saveItemToCart(item)}" ajax="false"/>
</ui:repeat>
</h:form>
and my bean
#ManagedBean
#SessionScoped
public class CartBean extends BaseBean {
private int quantityToOrder;
//setter, getter...
//When called quantityToOrder = 0 always
public void saveItemToOrder(Item item) {
quantityToOrder IS 0.
}
}
I suspect it has to do with form submission, I have tried a form enclosing all elements in the collection and also a form enclosing any of the spinners + button. The generated client IDs are distinct for all spinners.
Any help would be appreciated.
Put a System.out.println("quantity: " + quantityToOrder) on your setQuantityToOrder(int quantityToOrder) method and will will see the problem. The value of the last spinner will prevail over the others because all the spinners are pointed to the same property (cartBean.quantityToOrder).
Try moving the quantityToOrder to the Item as follows:
<h:form id="mainForm">
<ui:repeat value="#{cartBean.items}" var="item">
<p:outputLabel value="#{item.name}: " for="sp" />
<p:spinner id="sp" size="2" min="1" max="50" style="width:75px" value="#{item.quantityToOrder}" />
<p:commandButton value="Add to cart" action="#{cartBean.saveItemToOrder(item)}" process="#this, sp" update=":mainForm:total" />
<br />
</ui:repeat>
Total: <h:outputText id="total" value="#{cartBean.quantityToOrder}" />
</h:form>
The cartBean:
import java.io.Serializable;
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 CartBean implements Serializable {
private List<CartItem> items;
private int quantityToOrder;
#PostConstruct
public void setup() {
items = new ArrayList<CartItem>();
items.add(new CartItem(1, "A"));
items.add(new CartItem(2, "B"));
items.add(new CartItem(3, "C"));
}
public void saveItemToOrder(CartItem item) {
//do whatever you want to do with the item quantity.
System.out.println("Qtd of " + item.getName() + ": " + item.getQuantityToOrder());
//to calculte the qtd of items on the cart.
quantityToOrder = 0;
for (CartItem cartItem : items) {
quantityToOrder += cartItem.getQuantityToOrder();
}
}
public List<CartItem> getItems() {
return items;
}
public void setItems(List<CartItem> items) {
this.items = items;
}
public int getQuantityToOrder() {
return quantityToOrder;
}
public void setQuantityToOrder(int quantityToOrder) {
this.quantityToOrder = quantityToOrder;
}
}
The CartItem:
import java.io.Serializable;
public class CartItem implements Serializable {
private Integer id;
private Integer quantityToOrder;
private String name;
public CartItem(Integer id, String name) {
this.id = id;
this.name = name;
quantityToOrder = 0;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getQuantityToOrder() {
return quantityToOrder;
}
public void setQuantityToOrder(Integer quantityToOrder) {
this.quantityToOrder = quantityToOrder;
}
#Override
public int hashCode() {
int hash = 7;
hash = 67 * hash + (this.id != null ? this.id.hashCode() : 0);
return hash;
}
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CartItem other = (CartItem) obj;
if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) {
return false;
}
return true;
}
}

select onemenu values willbe disaplyed in hashcode format in the data table

i tried disply the roleid values from the Permissions pojo class into data table
here my problem it displays hash values insted of original values
my bean class is:
<f:facet name="header">
Role Details
</f:facet>
<p:column headerText="Roleid" sortBy="#{ps.roleid}">
<p:selectOneMenu id="role_id" value="#{ps.roleid}" >
<f:selectItems value="#{one.p}" var="vv" itemLabel="#{vv}"
itemValue="#{vv}" />
</p:selectOneMenu>
</p:column>
my pojo class is:
one.java
private String roleid;
private String object_type;
private int object_id;
private int below;
private int high;
private boolean self;
private boolean exclude;
public String getRoleid() {
return roleid;
}
public void setRoleid(String roleid) {
this.roleid = roleid;
}
public String getObject_type() {
return object_type;
}
public void setObject_type(String object_type) {
this.object_type = object_type;
}
public int getObject_id() {
return object_id;
}
public void setObject_id(int object_id) {
this.object_id = object_id;
}
public int getBelow() {
return below;
}
public void setBelow(int below) {
this.below = below;
}
public int getHigh() {
return high;
}
public void setHigh(int high) {
this.high = high;
}
public boolean isSelf() {
return self;
}
public void setSelf(boolean self) {
this.self = self;
}
public boolean isExclude() {
return exclude;
}
public void setExclude(boolean exclude) {
this.exclude = exclude;
}
}
If you want to show the roleid property as item label then just write code accordingly? Right now you're printing the whole object (which implicitly shows its toString() value) instead of the property.
Replace
itemLabel="#{vv}"
by
itemLabel="#{vv.roleid}"
That "hashcode format" is by the way just the default outcome of the Object#toString() method which will be used if you don't have a #Override public String toString() { ... } in your custom class.

Resources