My question should be trivial for someone who is familiar with Primefaces but I'm just starting. My question is:
When I put inputText component to my web page like this:
<h:form id="formularz">
<p:inputText id="workyears" value="#{appointentBean.year}" style="width: 40px;"/>
<h:form>
I would like to retrieve the inputed text directly from appointentBean. I mean I would like to create another method in appointentBean that will process inputed text so I need inputed text to be placed in referenced field year immediately. In another worlds I need my field year in appointentBean to be automaticaly updated while someone put text in inputText component. Something like submit? I hope you understand what I mean.
Here is my managedBean:
#ManagedBean
#ViewScoped
#SessionScoped
public class appointentBean{
private int year;
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
//Here I will put another method that will be operate on year value
}
You can do that using events like this (read more):
<h:form>
<p:inputText value="#{viewMBean.hello}">
<p:ajax event="keyup" update="hello" process="#this" />
</p:inputText>
<h:outputText id="hello" value="#{viewMBean.hello}" />
</h:form>
Here is the viewMBean:
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class ViewMBean implements Serializable {
private String hello;
public String getHello() {
return hello;
}
public void setHello(String hello) {
this.hello = hello;
}
}
PS: Welcome to Primefaces!!
Related
I am currently working on a project using Primefaces 4.0 and JEE 6. As a build-tool we use maven, and we got a JBoss Application Server.
So it was supposed to be simple. When a validation error occurs, I was supposed to prevent a tab-change in my view. Nothing big, but it needed to be done.
What happened next totally flabberghasted me, but first what I did:
Define a backing bean to handle the event.
Define a listener there.
Use <p:ajax /> to fire the tabChange event to my bean.
Well it was simple enough until there. When there were no validation errors, it worked just fine. Then I tried to validate the values in the view against my Model-Bean and was quickly stopped in my tracks.
As soon as I willingly produced errors in the View, to trigger the faces messages, the tabChange listener was not executed anymore. In fact, not even the #RequestScoped controller-class with the listener was constructed.
I proceeded to create a minimal working example with help of the Weld CDI maven archetype.
Now here I stand, at wits end and present to you my example:
home.xhtml:
I removed the surrounding xml-declaration and ui:define stuff, but that's what I took to reproduce it.
<h1>Hello World!</h1>
<p>
Your CDI bean
<code>HelloWorld</code>
says <span style="color: blue;">#{helloWorld.text}</span> using the
Unified EL.
</p>
<h:form id="bv">
<h2>Bean Validation examples</h2>
<p>Enforces annotation-based constraints defined on the model
class.</p>
<p:tabView id="tabView" effect="fade"
effectDuration="normal">
<p:ajax event="tabChange" update="tabView" listener="#{controller.tabChange}"/>
<p:tab title="Tab 1">
<table>
<tr>
<th style="text-align: right;"><h:outputLabel for="letters"
value="Letters:" /></th>
<td><p:inputText id="letters" value="#{helloWorld.letters}" />
<p:message for="letters" errorClass="invalid" /></td>
</tr>
</table>
</p:tab>
<p:tab title="Tab 2">
<p>Random text to be displayed</p>
</p:tab>
</p:tabView>
</h:form>
Controller.java:
here I only removed the package-declaration, for the protection of the innocent.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.primefaces.event.TabChangeEvent;
#Named
#RequestScoped
public class Controller implements Serializable {
private static final long serialVersionUID = -1126987875831465303L;
public Controller() {
}
#PostConstruct
public void init() {
System.out.println("Constructed " + this.getClass().getSimpleName());
}
public void tabChange(final TabChangeEvent event) {
System.out.println("Listener was reached");
}
}
Last but not least, the model-bean, slightly shortened from what the archetype provides:
HelloWorld.java:
Again I removed the namespace declaration.
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Model;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.NotEmpty;
public #Model
class HelloWorld {
private final String text = "Hello World!";
private String letters;
public HelloWorld() {
}
#PostConstruct
public void initialize() {
System.out
.println(this.getClass().getSimpleName() + " was constructed");
}
public String getText() {
return text;
}
#NotNull
#NotEmpty
#Pattern(regexp = "[A-Za-z]*", message = "must contain only letters")
public String getLetters() {
return letters;
}
public void setLetters(final String letters) {
this.letters = letters;
}
}
It seems that the JSF lifecycle interferes with what I want to do.
Taken from this german webiste:
It seems, that the event listener will only get invoked in the "Invoke Application"-phase.
Assuming that, it becomes quite obvious, that after "Process Validations" we skip to "Render Response" and our whole backing bean gets ignored.
It is possible to circumvent this, using immediate="true", but upon realizing there is a way better solution to the underlying problem I used that on, namely <p:wizard /> instead, that does exactly what I want.
Hi there i currently have a web page that uses ajax on submit to display the message the user entered on the same page below the input box, what i am wondering, if it is possible to keep a record of all messages inputted such as message 1, message 2 etc all displayed under them?
what is the best method for this ? also is there a way to do this with out the user having to press the submit button each time ?
this is my code so far :
<h:body>
<h3>JSF 2.0 + Ajax Hello World Example</h3>
<h:form>
<h:inputText id="name" value="#{helloBean.name}"></h:inputText>
<h:commandButton value="Welcome Me">
<f:ajax execute="name" render="output" />
</h:commandButton>
<h2><h:outputText id="output" value="#{helloBean.sayWelcome}" /></h2>
</h:form>
</h:body>
my bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import java.io.Serializable;
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSayWelcome(){
//check if null?
if("".equals(name) || name ==null){
return "";
}else{
return "Ajax message : Welcome " + name;
}
}
}
First you will need to change your bean. Make the attribute a List<String> to store all of the messages.
After that, to show the list you need to change output to a component that allows for showing all elements of the List; v.g. dataTable.
Also, you will need to invoke an action method in you ajax request, because your application will need to execute some logic (add name to the list).
I am trying to make a dynamic menu such that when something is selected in the first selector, the second one is populated from the database based on the selection in the first one. Here is the .xhtml:
<f:view>
<h:form>
<h:selectOneMenu id="seasonSelector" value ="#{selector_bean.season}">
<f:ajax event="valueChange" listener="#{selector_bean.genEvents}"
execute="seasonSelector" render="eventSelector" />
<f:selectItems value ="#{selector_bean.seasons}" var ="s"
itemLabel="#{s.getRange()}"
itemValue="#{s}"></f:selectItems>
</h:selectOneMenu>
<h:selectOneMenu id="eventSelector">
<f:selectItems value ="#{selector_bean.events}" var ="e"
itemLabel="#{e.event_Name}"
itemValue="#{e}"></f:selectItems>
</h:selectOneMenu>
</h:form>
</f:view>
Here is the bean:
#ManagedBean(name = "selector_bean")
#Stateless
public class selector_bean implements Serializable{
#EJB
SeasonFacade sf;
#EJB
EventFacade ef;
#EJB
WrestlerFacade wf;
private Season season;
private Event event;
private List<Event> events;
private Match match;
private Wrestler wrestler;
public List<Season> getSeasons(){
return sf.findAll();
}
public void genEvents(AjaxBehaviorEvent event){
events = (ef.findBySeason(season));
}
// setters and getters after this
When I change the value of the first selectOneMenu, a popup box appears with this message:
httpError: There was an error communicating with the server, status: 404
I am new to both JSF and AJAX so feel free to tear me apart if I am doing it wrong. Thanks for any help!
Your #ManagedBean is behaving as an EJB with the #Stateless annotation. Remove it and instead set the scope of your bean to #ViewScoped:
#ManagedBean(name = "selectorBean")
#ViewScoped
public class SelectorBean implements Serializable{
//your implementation...
}
Also, make sure to follow the JavaBean naming conventions. I've changed the name of your class to start with capital letter.
1.1, IceFaces 3.0.1 and JSF 2.1 and was trying to work with ace:fileentry. I can't understand why the listener is never called! Even the IDE sends me a warning "pruebaBean.sampleListener is an unknown property".
Here is a short example of what i'm doing. When click the submit button nothing happen.
Can someone help me ?? Could be some kind of bug?
prueba.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:h="http://java.sun.com/jsf/html"
xmlns:ice="http://www.icesoft.com/icefaces/component"
xmlns:ace="http://www.icefaces.org/icefaces/components">
<h:head>
</h:head>
<h:body>
<ice:form id="usuarioForm">
<ice:panelGrid columns="2">
<ace:fileEntry id="fileEntryImage" absolutePath="c:\iTablero\imagenes"
useSessionSubdir="false" useOriginalFilename="false"
fileEntryListener="#{pruebaBean.sampleListener}"/>
<ice:commandButton type="submit" value="Subir archivo"/>
</ice:panelGrid>
<ice:messages/>
</ice:form>
</h:body>
PruebaBean.java:
package com.itablero.backingbeans;
import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.faces.bean.RequestScoped;
import org.icefaces.ace.component.fileentry.FileEntry;
import org.icefaces.ace.component.fileentry.FileEntryEvent;
import org.springframework.stereotype.Controller;
#ManagedBean
#Controller
#RequestScoped
public class PruebaBean implements Serializable {
public void sampleListener (FileEntryEvent e) {
System.out.println("it work!");
FileEntry fe = (FileEntry) e.getComponent();
//some others operations
}
}
Update 1
Thanks to #fischermatte I found the problem was replace ice:commandButton for h:commandButton. But when I applied this to the original complete form and didn't work. The fileEntryListener method is never called. Can someone see the error here?
Logically the previous example and the code below have the same web.xml, faces-config.xml, etc. Note the button to submit the file is h:commandButton, and there is a ice:commandButton for complete form. I already tried to change this por en h:cb.
Here is the original form (that is display in a popup/modal window) and bean:
usuariosList.xhtml
<ice:panelPopup rendered="#{usuariosBean.showPopup}"
visible="#{usuariosBean.showPopup}"
modal="true"
autoCentre="true">
<f:facet name="header">
<h:panelGroup>
<h:panelGroup style="float: left;">
Usuario
</h:panelGroup>
<h:panelGroup style="float: right;">
<ice:form>
<h:commandButton image="/resources/images/popup-close.png"
alt="Cerrar" title="Cerrar"
style="height: 11px; width: 11px; border: 0;"
action="#{usuariosBean.closePopup}"/>
</ice:form>
</h:panelGroup>
</h:panelGroup>
</f:facet>
<f:facet name="body">
<ice:form id="usuarioForm">
<ice:panelGrid columns="2">
<p>Nombre:</p>
<ice:inputText id="nombre" label="nombre" value="#{usuariosBean.usuario.nombre}" size="40" />
<p>Imagen:</p>
<ice:graphicImage value="#{usuariosBean.usuario.imagen}"/>
<ace:fileEntry id="fileEntryImage" absolutePath="c:\iTablero\imagenes"
useSessionSubdir="false" useOriginalFilename="false"
fileEntryListener="#{usuariosBean.formListener}"/>
<h:commandButton type="submit" value="Subir archivo"/>
</ice:panelGrid>
<ice:messages for="usuarioForm"/>
<ice:commandButton value="Guardar" action="#{usuariosBean.save()}" />
</ice:form>
</f:facet>
</ice:panelPopup>
UsuariosBean.java
package com.itablero.backingbeans;
import com.itablero.excepciones.DAOException;
import com.itablero.modelo.Usuario;
import com.itablero.servicios.AdminService;
import java.io.Serializable;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.icefaces.ace.component.fileentry.FileEntry;
import org.icefaces.ace.component.fileentry.FileEntryEvent;
import org.icefaces.ace.component.fileentry.FileEntryResults;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
#ManagedBean
#Controller
#ViewScoped
public class UsuariosBean implements Serializable {
#Autowired
private AdminBean adminBean;
#Autowired
private AdminService adminService;
private Usuario usuario = new Usuario();
private boolean showPopup;
//getter and setters
public boolean isShowPopup() {
return showPopup;
}
public void setShowPopup(boolean showPopup) {
this.showPopup = showPopup;
}
public void openPopup() {
this.showPopup = true;
}
public void closePopup() {
this.showPopup = false;
this.usuario = new Usuario();
}
public String edit(Usuario usuario) {
this.usuario = usuario;
this.showPopup = true;
return "usuariosList";
}
public String delete(Usuario usuario) {
adminService.delete(usuario);
return "usuariosList";
}
public String save() {
try {
usuario.setTutor(adminBean.getLoggedTutor());
adminService.save(usuario);
} catch (DAOException ex) {
Logger.getLogger(TutoresBean.class.getName()).log(Level.SEVERE, null, ex);
}
usuario = new Usuario();
this.showPopup = false;
return "usuariosList";
}
public void formListener(FileEntryEvent e) {
System.out.println("Entro");
FileEntry fe = (FileEntry)e.getComponent();
FileEntryResults results = fe.getResults();
//other stuff
}
}
Update 2
I think I figured out why is not working, but need some help with the fix. I made the corrections as #fischermatte advice me, but didn't work.
To reach this page with the form, first have to navigate throw a the main page /admin/admin.html, if a look the URL in the browser appears http://localhost:8084/iTablero/admin/admin.html. This page has a menu, one of this menu options bring me to the page with the problematic form. But, because is an AJAX call (if i'm not wrong) the URL in the browser does not change, it keeps the http://localhost:8084/iTablero/admin/admin.html. And the fileEntry never calls the listener.
Now, if I enter the URL by myself http://localhost:8084/iTablero/admin/usuariosList.html, the page is displayed correctly as before, but now THE FILEENTRY WORKS PERFECTLY!!!
I have no idea how to fix this, will have to use redirects? I think is something around AJAX.......help pls! :-D
Update 3
That is the menu, without redirect is not working.
<h:form>
<ice:menuBar orientation="horizontal">
<ice:menuItem value="Tutores" action="tutoresList"/>
<ice:menuItem value="Usuarios" action="usuariosList"/>
<ice:menuItem value="Tableros" action="tablerosList"/>
<ice:menuItem value="Simbolos" action="simbolosList"/>
<ice:menuItem value="Estadisticas" action="estadisticas"/>
<ice:menuItem value="Salir" action="#{adminBean.logout()}"/>
</ice:menuBar>
</h:form>
With action="usuariosList?faces-redirect=true" works fine.
Already test with forward navigation to a basic page form with only a FileEntry and doesn't work too. Again, if I use redirect, works fine. I think is some kind of issue with this component and forward navigation.
You have to use JSF's commandbutton instead of icefaces's: <h:commandButton type="submit" value="Subir archivo"/>. It is a known issue in ICEFaces, see ace:fileEntry wiki.
Update 1
Plus you either remove the rendered attribute in the popup or update the popup when opening it like here:
<h:form>
<h:commandButton value="Show Popup" action="#{usuariosBean.showPopupAction}">
<f:ajax render=":popupPanelGroup"/>
</h:commandButton>
</h:form>
<h:panelGroup id="popupPanelGroup">
<ice:panelPopup visible="#{usuariosBean.showPopup}" rendered="#{usuariosBean.showPopup}" modal="true" autoCentre="true">
...
</ice:panelPopup>
</h:panelGroup>
I have this form:
<h:form>
<h:outputText value="Tag:" />
<h:inputText value="#{entryRecorder.tag}">
<f:ajax render="category" />
</h:inputText>
<h:outputText value="Category:" />
<h:inputText value="#{entryRecorder.category}" id="category" />
</h:form>
What I'm trying to achieve: When you type in the "tag" field, the entryRecorder.tag field is updated with what was typed. By some logic upon this action the bean also updates its category field. This change should be reflected in the form.
Questions:
What scope shall I use for EntryRecorder? Request may not be satisfactory for multiple AJAX requests, while session will not work with multiple browser windows per one session.
How can I register my updateCategory() action in EntryRecorder so that it is triggered when the bean is updated?
Answering point 2:
<h:inputText styleClass="id_tag" value="#{entryRecorder.tag}"
valueChangeListener="#{entryRecorder.tagUpdated}">
<f:ajax render="category" event="blur" />
</h:inputText>
Bean:
#ManagedBean
#ViewScoped
public class EntryRecorder {
private String tag;
private String category;
#EJB
private ExpenseService expenseService;
public void tagUpdated(ValueChangeEvent e) {
String value = (String) e.getNewValue();
setCategory(expenseService.getCategory(value));
}
}
Number 1, anybody?
To point 1, I'll use Request since there is no need to use View and Session is, as you well pointed, completely unnecessary.
For point 2, since you are using <f:ajax/> I suggest making full use of it. Here is my proposal:
xhtml:
<h:form>
<h:outputText value="Tag:" />
<h:inputText value="#{entryRecorder.tag}">
<f:ajax render="category" event="valueChange"/>
</h:inputText>
<h:outputText value="Category:" />
<h:inputText value="#{entryRecorder.category}" id="category" />
</h:form>
Note the use of valueChange event instead of blur (not that blur doesn't work but I find valueChange more 'proper' for a value holder component).
bean:
#ManagedBean
#RequestScoped
public class EntryRecorder {
private String tag;
private String category;
public String getCategory() {
return category;
}
public String getTag() {
return tag;
}
public void setCategory(String category) {
this.category = category;
}
public void setTag(String tag) {
this.tag = tag;
tagUpdated();
}
private void tagUpdated() {
category = tag;
}
}
Unless you really want the tagUpdated method executed only when tag is updated through the view, my proposal looks more clear. You don't have to deal with the events (nor casting) and the tagUpdated method can be private hiding it's functionality from possible misuses.