Clicking on commandLink is invoking preRenderView again - ajax

In my facelet, I have the below commandLink:
<h:form>
<p:commandLink id="excelExport" action="#{studentBean.exportReport()}" ajax="false">
<f:param name="type" value="EXCEL" />
<p:graphicImage library="img" name="excel.png" width="20" />
</p:commandLink>
</h:form>
This is what I am having in my backing bean:
#ManagedBean
#RequestScoped
public class StudentBean implements Serializable {
.............
#ManagedProperty(value = "#{param.type}")
private String typeOfExport;
.............
public void preRender(ComponentSystemEvent event) {
System.out.println("Inside prerender");
if (FacesHelper.isAjaxRequest()) {
return;
}
}
.............
public void exportReport() {
System.out.println("Type of Report is: " + typeOfExport);
}
}
Now I would like to execute the method exportReport once I click on the commandLink. But what is happening here is that after executing the method, it is going to preRender again. I don't want to render the entire form again. Any idea what mistake I am doing here?

Related

Passing Managedbean property

I've two session scoped beans I need to pass values between them through f:setPropertyActionListener but I cant read it from receivable end.
<p:selectOneListbox style="height: 100%; width: 100%" id="lstSubject" required="true" requiredMessage="Please select any Subject"
value="#{chooseSubExamManagedBean.subId}" >
<f:selectItems value="#{chooseSubExamManagedBean.mapSubjects}" />
</p:selectOneListbox>
user chooses the subject and I've to pass this id from p:command button to another bean
<p:commandButton id="cmdProceed" value="Proceed" action="#{chooseSubExamManagedBean.gotoFillMarks}" >
<f:setPropertyActionListener target="#{fillMarksManagedBean.subId}" value="#{chooseSubExamManagedBean.subId}" />
</p:commandButton>
the managed bean fillMarksManagedBean
#Named(value = "fillMarksManagedBean")
#javax.enterprise.context.SessionScoped
public class FillMarksManagedBean implements Serializable{
private int SubId;
private String ExamDetail;
public void setSubId(int SubId) {
this.SubId = SubId;
}
public int getSubExamId() {
return SubExamId;
}
and use that subId in
#PostConstruct
public void init() {
ExamDetail = clsFillMarks.getExamDetail(SubId);
}
...
How do i do this?
Thanks in advance

JSF2.0 popup show after the second click

I have 3 managebean one model and 2 controllers (1 for the popup text) i want a popup after i insert into the database.
my page is like this the problem is that when i call for mensaje.mostrar() i works but when i try to call cursoControlador.registrarCurso() and from there try to call mensaje.mostrar() that changes the value from mostrarMensaje (boolean) don't show the popup.
<ui:define name="centro">
<h:form>
<h:panelGrid columns="3" cellpadding="5">
<p:outputLabel value="Nombre" />
<p:inputText value="#{cursoModelo.nombre}"/>
this is the button use and works fine
<p:commandButton action="#{mesaje.mostrar()}" value="Registrar Curso" >
<f:ajax render="#form"/>
</p:commandButton>
and this is the behavior i want
<p:commandButton action="#{cursoControlador.registrarCurso()}" value="Registrar Curso" >
<f:ajax render="#form"/>
</p:commandButton>
and this is the popup message i want to show
</h:panelGrid>
<h:panelGroup layout="block" styleClass="fondo-popup" rendered="#{mensaje.mostrarMensaje}">
<div class="panel-popup">
<p:outputLabel value="#{mensaje.texto}"/>
<h:commandButton value="Aceptar" action="#{mensaje.esconder()}">
<f:ajax render="#form"/>
</h:commandButton>
</div>
</h:panelGroup>
</h:form>
</ui:define>
model
#Named(value = "cursoModelo")
#SessionScoped
public class CursoModelo implements Serializable {
private String nombre;
//getters and setters...
}
controller 1
#Named(value = "cursoControlador")
#SessionScoped
public class CursoControlador implements Serializable{
#Inject private CursoModelo cursoModelo;
#Inject private Mensaje mensaje;
/**
* Creates a new instance of CursoControlador
*/
public CursoControlador() {
}
public String registrarCurso(){
//SOME CODE that inserts into de database
mensaje.mostrar(); //this is the problem probably i'm doing it wrong
return "index";
}
}
controller 2 (The controller for the message)
#Named(value = "mensaje")
#SessionScoped
public class Mensaje implements Serializable {
private String texto;
private boolean mostrarMensaje;
/**
* Creates a new instance of Mensaje
*/
public Mensaje() {
texto = "Mensaje a mostrar";
mostrarMensaje = false;
}
public void mostrar(){
mostrarMensaje = true;
}
public void esconder(){
mostrarMensaje = false;
}
//getters and setters from texto and mostrarMensaje
}

Can I call multiple methods from <p:ajax event=select listner=method1, metho2>?

Can I call multiple methods from the ajax event select in listener?
<p:tree value="#{ddTreeBean.root}" var="node" dynamic="true"
selectionMode="single" selection="#{ddTreeBean.selectedNode}">
<p:ajax event="select" listener="#{data2.refresh}"
update=":pchartId,:panelId">
</p:ajax>
<p:treeNode type="node" expandedIcon="folder-open"
collapsedIcon="folder-collapsed">
<h:outputText value="#{node.name}" />
</p:treeNode>
<p:treeNode type="leaf" icon="document-node">
<h:outputText value="#{node.name}" />
</p:treeNode>
</p:tree>
on a select I need to bind my listener to two methods?
Is that allowed?
I have a tree and when I make a selection, I need to update (trigger) two components (two other back beans).
Does listener attribute take two parameters (two method names)?
THanks.
Myclass1 class {
method1();
}
Myclass2 class {
method2();
}
If you want to call a method of one ManagedBean from another, you have to Inject the other ManagedBean.
#ManagedBean
public class MyBean1{
public void methodAbc(){
...
}
}
Inject in to
#ManagedBean
public class MyBean2{
#ManagedProperty(value = "#{myBean1}")
private MyBean1 mybean1;
//SETTER GETTER for mybean1
public void myAction(){
mybean1.methodAbc();
}
}
Compatible ManagedBean Injection scoped are given in following table(courtesy of Core Java Server Faces Book):
OR You can dynalically resolve EL expression in your Action method itself as follows.
public void myAction(){
FacesContext fctx = FacesContext.getCurrentInstance();
MyBean1 mybean1 = fctx.getApplication().evaluateExpressionGet(fctx , "#{myBean1}", MyBean1.class);
mybean1.methodAbc();
}
Since you are using Primefaces there is one more way to do this, using p:remoteCommand :
<p:ajax event="select" listener="#{data2.refresh}"
update=":pchartId,:panelId"
oncomplete="callRemote2()"/>
<p:remoteCommand name="callRemote" partialSubmit="true" process="#this"
action="#{yourmanagedbean.method2}" />
No, it doesn't. You can have a single method where you call the two or more methods you need to execute:
<p:ajax event="select" listener="#{someMB.multipleMethods}" update=":pchartId,:panelId" />
And in Java side
#ManagedBean
#ViewScoped
public class SomeMB {
public void method1() { /* */ }
public void method2() { /* */ }
public void multipleMethods() {
method1();
method2();
}
}
If you need to use several managed beans, an option is to inject one into the other:
#ManagedBean
#SessionScoped
public class AnotherMB {
public void method2() { /* */ }
}
#ManagedBean
#ViewScoped
public class SomeMB {
#ManagedProperty("#{anotherMB}")
AnotherMB anotherMB;
//provide a setter
public void setAnotherMB(AnotherMB anotherMB) {
this.anotherMB = anotherMB;
}
public void method1() { /* */ }
public void multipleMethods() {
method1();
anotherMB.method2();
}
}

Ajax event does not fire on JSF page when an item is selected (update)

I am learning JavaEE and I am playing around with ajax call with jsf and managedbean. I am trying to display the text as soon as i change the value from the drop down list. I see many people have the same problem on stackoverflow and i try to follow answers that are marked as accepted but I still can't make it work. Can someone please tell me where my error is?
Here is the jsf code:
<h:form>
<h:selectOneMenu id="productlist" value="#{productRepoMB.selectedProduct}">
<f:selectItems value="#{productRepoMB.productList}" var="product" itemValue="#{product.productID}" />
<f:ajax event="valueChange"
render="result"
listener="#{productRepoMB.selectMenuListener}" />
</h:selectOneMenu>
text changed: <h:outputText id="result" value="#{productRepoMB.text}" />
</h:form>
Here is managed bean code, Products list is populated from a database:
#Named
#RequestScoped
public class ProductRepoMB implements Serializable {
#EJB
private ProductsRepo productRepo;
private Products selectedProduct;
private List<Products> productList;
private String text="init text"; //use for testing ajax call
public ProductRepoMB() {
}
public Products getSelectedProduct() {
return selectedProduct;
}
public List<Products> getProductList() {
productList = productRepo.findAll();
return productList;
}
//The following code are used to testing ajax only!
public void selectMenuListener(AjaxBehaviorEvent e) {
setText("changed!");
}
public String getText() {
return text;
}
public void setText(String text){
this.text = text;
}
}

malformedXML: During update: accessForm:passMessage not found

I'm trying to improve my web app. I read this article http://balusc.blogspot.com/2011/01/jsf-20-tutorial-with-eclipse-and.html and tried to implement some of the ajax stuff (I'm very new to JSF and Ajax).
So the first form works as expected, but when I pass to the second page the message malformedXML: During update: accessForm:passMessage not found is shown in an alert box.
Can anyone explain me why?
<h:form id="accessForm">
<h:panelGrid columns="3">
<h:outputLabel for="user" value="Usuario:"
style="float: right" />
<h:inputText id="user" value="#{userVerifier.username}"
required="true"
requiredMessage="Introduzca su nombre de usuario.">
<f:ajax event="blur" render="userMessage" />
</h:inputText>
<h:message id="userMessage" for="user" style="color: #FF0000;" />
<h:outputLabel for="pass" value="ContraseƱa:"
style="float: right" />
<h:inputSecret id="pass" value="#{userVerifier.password}"
required="true"
requiredMessage="Introduzca su contraseƱa." redisplay="true">
<f:ajax event="blur" render="passMessage" />
</h:inputSecret>
<h:message id="passMessage" for="pass" style="color: #FF0000;" />
<h:panelGroup />
<h:commandButton value=" Entrar " action="#{userVerifier.check}"
style="float: right" >
<f:ajax execute="#form" render="#form" />
</h:commandButton>
<h:messages globalOnly="true" layout="table" />
</h:panelGrid>
</h:form>
Thanks in advance.
Update
Here's the Bean code:
#ManagedBean
#SessionScoped
public class UserVerifier{
private String username;
private String password;
private String dependencia;
private String tipoUsuario;
private final Database db = new Database();
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDependencia() {
return dependencia;
}
public void setDependencia(String dependencia) {
this.dependencia = dependencia;
}
public String getTipoUsuario() {
return tipoUsuario;
}
public void setTipoUsuario(String tipoUsuario) {
this.tipoUsuario = tipoUsuario;
}
public String check() {
String isValidUser = db.checkUser(username, password);
if (isValidUser.equals("T")) {
dependencia = db.getDependencia(username, password);
tipoUsuario = db.getTipoUsuario(username);
System.out.println("tipoDepe: " + dependencia);
System.out.println("tipoUser: " + tipoUsuario);
if (dependencia != null && tipoUsuario != null) {
return "upload-file";
} else {
setUsername("");
setPassword("");
return "index";
}
} else if (isValidUser.equals("F")) {
setUsername("");
setPassword("");
return "index";
} else {
return "error-pnf";
}
}
}
This error indicates a race condition in handling ajax requests. The ajax request of the action method occurred before the ajax request of the blur validation. Try adding ?faces-redirect=true to the navigation outcome value of the action method. JSF should then surely block all open ajax requests in the queue.
public String check() {
// ...
return "nextpage?faces-redirect=true";
}
Using (default) forward on POST navigation is a poor practice anyway as the enduser would otherwise end up with an unchanged URL in browser address bar and a non-bookmarkable page. See also When should I use h:outputLink instead of h:commandLink?

Resources