PF SetPropertyActionListener breaks after first time - ajax

i've a problem that's driving me crazy! I have a component which renders a panel that have links on a footer. This links have, among other things, a title and HTML content I want to show. The idea is basically that when a link is clicked, the content of the page is changed via ajax and the html content of the link is shown (The footer remains on the page). Debbuging I've noticed that the first time a link is clicked the content does change, but then it doesn't. The setPropertyActionListener of the p.commandlinks in my composite component aren't executed any more after first time. I'have debbuged the project and this seems to be the problem, but I can't figure out why
Part of my composite component. Tryed setting an onstart and oncomplete js functions on the command link, and both are executed but the actionListeners aren't.
<cc:interface>
<cc:attribute name="compId"/>
<cc:attribute name="title"/>
<cc:attribute name="bean"/>
...
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<p:panel id="#{cc.attrs.compId}" header="#{cc.attrs.title}"
widgetVar="#{cc.attrs.compId}"
styleClass="#{cc.attrs.styleClass}">
<h:form>
<p:dataList id="datalist-#{cc.attrs.compId}" value="#{cc.attrs.bean.currentList}"
type="definition" widgetVar="datalist-#{cc.attrs.compId}"
var="items" >
<p:commandLink action="#{navBean.active}" update="#([id$=content])" styleClass="link"
value="#{items.descrInLang}" rendered="#{items.typeUrl eq 0}">
<f:setPropertyActionListener value="infoPage" target="#{navBean.selection}"/>
<f:setPropertyActionListener value="#{items.descrInLang}" target="#{infoPage.title}" />
<f:setPropertyActionListener value="#{items.HTMLContent}" target="#{infoPage.HTMLContent}"/>
</p:commandLink>
</p:dataList>
</h:form>
</p:panel>
</cc:implementation>
Part of my Navigation Bean
public void active() throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException {
setAlbums(selection.equals("albums"));
setBand(selection.equals("band"));
setConcerts(selection.equals("concerts"));
setContacts(selection.equals("contacts"));
setHome(selection.equals("home"));
setSiteMap(selection.equals("siteMap"));
setInfoPage(selection.equals("infoPage"));
}
public void setSelection(String selection) {
this.selection = selection;
}
public boolean isInfoPage() {
return infoPage;
}
public void setInfoPage(boolean infoPage) {
this.infoPage = infoPage;
}
The bean which stores the title & HTML Content to show. After the first click on the link, the getters of Title & HTML content are executed, but the setters aren't (as declared in the setPropertyActionListeners)
#ManagedBean
#SessionScoped
public class InfoPage implements Serializable {
private String title;
private String HTMLContent;
public InfoPage() {
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getHTMLContent() {
return HTMLContent;
}
public void setHTMLContent(String HTMLContent) {
this.HTMLContent = HTMLContent;
}
}
The content part of the template which indicates what content should be shown according to the selected page on the NavBean. I pass the HTML content and the title of the infoPage as a parameter
<h:head>
</h:head>
<h:body>
<!-- the all containing file -->
<ui:composition template="template.xhtml">
<ui:define name="content">
<h:panelGroup layout="block" id="content">
<h:panelGroup layout="block" rendered="#{navBean.home}">
<ui:include src="homecontent.xhtml"/>
</h:panelGroup>
....
<h:panelGroup layout="block" rendered="#{navBean.infoPage}">
<ui:include src="infoPage.xhtml">
<ui:param name="title" value="#{infoPage.title}"/>
<ui:param name="infoContent" value="#{infoPage.HTMLContent}"/>
</ui:include>
</h:panelGroup>
</h:panelGroup>
</ui:define>
</ui:composition>
</h:body>
The info Page.
<h:form id="infoPageForm">
<p:panel id="infoPagePanel" header="#{title}">
<h:panelGrid columns="1" cellpadding="10">
<h:outputText escape="false" value="#{infoContent}" />
</h:panelGrid>
</p:panel>
</h:form>
Thanks for your time!

Related

losing request parameter in jsf for second ajax poll call

I'm facing a problem with poll request, the first call is ok and the second is loosing the request parameter. Below is the code:
<h:form id="form">
<p:poll interval="10" listener="${emsstatbean.getEmsStat_list(request.getParameter('para'))}" update="emstatTable" />
<p:dataTable id="emstatTable" var="emsstat" value="${emsstatbean.getEmsStat_list(request.getParameter('para'))}" emptyMessage="No statistic found with given criteria" styleClass="table table-striped table-bordered table-hover" >
<p:column headerText="Server Hostname" >
<h:outputText value="#{emsstat.id.timeStamp}" />
</p:column>
<p:column headerText="Os name" >
<h:outputText value="#{emsstat.upTime}" />
</p:column>
<p:column headerText="Os name" >
<h:outputText value="${emsstat.state}" />
</p:column>
</p:dataTable>
</h:form>
and this is the bean class:
#ManagedBean(name = "emsstatbean")
public class EmsStatBean implements Serializable
{
public List<TibcoEmsStat> getEmsStat_list(int p)
{
return service.listEmsStats(p);
}
#ManagedProperty("#{emsStatService}")
EmsStatService service;
#PostConstruct
public void init()
{
}
public void setService(EmsStatService service)
{
this.service = service;
}
}
This is the URL called: content/public/TibcoEmsStat.xhtml?para=254
So when I paste that on browsers I'm getting the data table with all rows, but when I wait 10 sec I don't see content and I get "No statistic" found with given criteria, because parameter is empty.
Can you please help me to understand where is the issue?
this is how i fixed after reviewing some suggested link
added to the bean:
#ViewScoped
and a variable to store the id
public int ems_inst;
public int getEms_inst() {
return ems_inst;
}
public void setEms_inst(int ems_inst) {
this.ems_inst = ems_inst;
}
on the xhtml i did:
<f:metadata>
<f:viewParam name="ems_inst" value="#{emsstatbean.ems_inst}" />
</f:metadata>
<h:form id="form">
<p:poll interval="10"
listener="${emsstatbean.getEmsStat_list(emsstatbean.ems_inst)}" update="emstatTable" />
<p:dataTable id="emstatTable" var="emsstat" value="${emsstatbean.getEmsStat_list(emsstatbean.ems_inst)}"
all now is working fine
thanks

JSF ajax event does not work in form

Yesterday I created a really simple JSF project to practice how to render a dynamic menu with Ajax request.
The addition method works pretty well, but in case I switch to another tab the result is not calculated and displayed in the page.
I debugged the code for hours, but till yet I haven't found the root cause. Do you have any idea what the problem can be?
Web Pages
index.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://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Mathematics</title>
</h:head>
<h:body>
<h:panelGroup id="menu">
<h:form>
<f:ajax render="page">
<h:commandButton value="Addition" action="#{menuMB.setPage('addition')}"></h:commandButton>
<h:commandButton value="Subtraction" action="#{menuMB.setPage('subtraction')}"></h:commandButton>
<h:commandButton value="Multiplication" action="#{menuMB.setPage('multiplication')}"></h:commandButton>
<h:commandButton value="Division" action="#{menuMB.setPage('division')}"></h:commandButton>
</f:ajax>
</h:form>
</h:panelGroup>
<h:panelGroup id="page">
<ui:include src="/WEB-INF/includes/#{menuMB.page}.xhtml"/>
</h:panelGroup>
</h:body>
</html>
addition.xhtml
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:panelGroup id="header">
<h1>Addition</h1>
</h:panelGroup>
<h:panelGroup id="content">
<h:form id="addition">
<h:outputLabel for="number1" value="Number1:"/>
<h:inputText id="number1" value="#{mathMB.number1}">
<f:ajax event="keyup" listener="#{mathMB.addition}" execute="number1 number2" render="result"/>
</h:inputText>
<h:outputLabel for="number2" value="Number2:"/>
<h:inputText id="number2" value="#{mathMB.number2}">
<f:ajax event="keyup" listener="#{mathMB.addition}" execute="number1 number2" render="result"/>
</h:inputText>
<h:outputLabel for="result" value="Result:"/>
<h:outputText id="result" value="#{mathMB.result}"/>
</h:form>
</h:panelGroup>
All other xhtml pages (division, multiplication, subtraction) are the same as above, only the addition method is changed with the proper one.
Managed Beans
MathMB
#ManagedBean
#RequestScoped
public class MathMB {
private Integer number1;
private Integer number2;
private Integer result;
public void addition() {
if (number1 == null || number2 == null) {
return;
}
result = number1 + number2;
}
subtraction...
multiplication...
division...
//getters + setters
}
MenuMB
#ManagedBean
#ViewScoped
public class MenuMB implements Serializable {
private String page;
#PostConstruct
public void init() {
page = "addition";
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
}
Thanks a lot for any tips!
You need to put the <f:ajax> tag inside the commandbuttons, not the other way round.
<h:commandButton value="Addition" action="#{menuMB.setPage('addition')}">
<f:ajax render="page"/>
</h:commandButton>
<h:commandButton value="Subtraction" action="#{menuMB.setPage('subtraction')}">
<f:ajax render="page"/>
</h:commandButton>
...

inputHidden not being updated on immediate ajax action

I'm trying to code a JSF page with a pop-up dialog that allows users to enter data. I've used PrimeFaces before, but for various reasons I've decided not to use it for this project. After all, I just need a simple pop-up dialog. How hard could it be to code it myself?
The ways it's suppose to work is:
The user clicks the Add New Record button and the dialog is shown.
The user enters data and clicks the Save button.
If there are validation errors, the messages are displayed in the dialog and the dialog remains visible.
If there are no errors, a success message is shown on the main page and the dialog disappears.
The user can press the Cancel button to close the dialog without saving.
My problem is that when the user presses Save and gets validation errors and then presses Cancel, the dialog does not disappear. I can see that under this scenario, the value for the inputHidden field does not get updated to false. The isShowDialog() method on the backing bean does not get called.
Here is my facelet:
<?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">
<h:head>
<h:outputScript library="js" name="jquery-1.11.0.js" />
</h:head>
<h:body>
<h:messages id="pageMessages" errorStyle="color: red;" infoStyle="color: green;" />
<script type="text/javascript">
function showHideDialog(data) {
if (data.status == "success") {
if ($("#dialogForm\\:showDialog").val() == "true") {
$("#dialogDiv").show();
$("#pageMessages").hide();
} else {
$("#dialogDiv").hide();
$("#pageMessages").show();
}
}
}
</script>
<div id="dialogDiv" style="border: thick solid black; display: none;">
<h:form id="dialogForm">
<h:messages id="dialogMessages" errorStyle="color: red;" infoStyle="color: green;" />
<h:inputHidden id="showDialog" value="#{backingBean.showDialog}" />
<h:panelGrid columns="2">
<h:outputLabel for="dialogField" value="Some Field:" />
<h:inputText id="dialogField" value="#{backingBean.dialogField}" label="Some field" required="true" />
</h:panelGrid>
<h:commandButton value="Save" action="#{backingBean.save}">
<f:ajax event="action" execute=":dialogForm" render=":dialogForm :pageMessages" onevent="showHideDialog" />
</h:commandButton>
<h:commandButton value="Cancel" action="#{backingBean.cancel}" immediate="true">
<f:ajax event="action" render=":dialogForm :pageMessages" onevent="showHideDialog" />
</h:commandButton>
</h:form>
</div>
<h:form id="pageForm">
<p>Normal page content. Blah, blah, blah.</p>
<h:commandButton value="Add New Record" action="#{backingBean.addNew}">
<f:ajax event="action" render=":dialogForm :pageMessages" onevent="showHideDialog" />
</h:commandButton>
</h:form>
</h:body>
</html>
Here is my backing bean:
package com.mycompany.example;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class BackingBean {
private String dialogField;
private boolean showDialog = false;
public String addNew() {
dialogField = null;
showDialog = true;
return null;
}
public String save() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "New row successfully saved.", null));
showDialog = false;
return null;
}
public String cancel() {
showDialog = false;
return null;
}
public String getDialogField() { return dialogField; }
public void setDialogField(String dialogField) { this.dialogField = dialogField; }
public boolean isShowDialog() { return showDialog; }
public void setShowDialog(boolean showDialog) { this.showDialog = showDialog; }
}
If it matters, I'm using Mojarra 2.2.5 and Tomcat 7.0.42.
Any suggestions or insights would be appreciated.
I found an answer. I changed
<h:inputHidden id="showDialog" value="#{backingBean.showDialog}" />
to
<input id="dialogForm:showDialog" type="hidden" value="#{backingBean.showDialog}" />
I found the answer reading the following BalusC article: Okay, when should I use the immediate attribute?
In short, use
immediate="true" in <h:inputHidden id="showDialog" too,
and
execute="showDialog" in <f:ajax inside <h:commandButton value="Cancel".
P.S.: Your example code was very useful.

JSF dynamic include using Ajax request [duplicate]

This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 7 years ago.
In JSF2, is it possible to change the of value of src of ui:include dynamically using Ajax request (like for example PrimeFaces p:commandButton)?
Thank you.
<h:form>
<h:commandLink value="Display 2" action="#{fTRNav.doNav()}">
<f:setPropertyActionListener target="#{fTRNav.pageName}" value="/disp2.xhtml" />
</h:commandLink>
</h:form>
<ui:include src="#{fTRNav.pageName}"></ui:include>
That's what I have right now. Is it possible to make it Ajax (using p:commandButton)?
The JSTL tags as proposed in the other answer are not necessary and it is not nicely reuseable.
Here's a basic example using pure JSF (assuming that you runs Servlet 3.0 / EL 2.2, otherwise you indeed need to use <f:setPropertyActionListener> like as in your question):
<h:form>
<f:ajax render=":include">
<h:commandLink value="page1" action="#{bean.setPage('page1')}" />
<h:commandLink value="page2" action="#{bean.setPage('page2')}" />
<h:commandLink value="page3" action="#{bean.setPage('page3')}" />
</f:ajax>
</h:form>
<h:panelGroup id="include">
<ui:include src="#{bean.page}.xhtml" />
</h:panelGroup>
with
private String page;
#PostConstruct
public void init() {
this.page = "page1"; // Ensure that default is been set.
}
// Getter + setter.
here is how I render subcontent dynamically using MnagedBean. First I set page in the center (that will be changed by menu triggers) with private String name="/main_pages/mainpage.xhtml", then each time submenu is clicked the HelloBean resets "name" and contents is updated by update=":content" - then new name is retrieved from Bean:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
</f:facet>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="150" resizable="true" closable="true" collapsible="true">
<h1>Madeline<br>shop</br></h1>
</p:layoutUnit>
<p:layoutUnit position="south" size="100" closable="true" collapsible="true">
Zapraszamy do odwiedzania naszego biura!
</p:layoutUnit>
<p:layoutUnit position="west" size="175" header="Menu" collapsible="true">
<h:form>
<p:menu>
<f:ajax render=":content">
<p:menuitem value="O naszej agencji" action="#{helloBean.setName('/main_pages/onas.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia pojazdów" action="#{helloBean.setName('/main_pages/ubpoj.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia majątkowe" action="#{helloBean.setName('/main_pages/ubmaj.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia na życie" action="#{helloBean.setName('/main_pages/ubnaz.xhtml')}" update=":content" />
<p:menuitem value="Zapytaj" action="#{helloBean.setName('/main_pages/zapytaj.xhtml')}" update=":content" />
<p:menuitem value="Kontakt" action="#{helloBean.setName('/main_pages/kontakt.xhtml')}" update=":content" />
</f:ajax>
</p:menu>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<br></br><br></br>
<p:panel id="content">
<ui:include src="#{helloBean.name}" />
</p:panel>
</p:layoutUnit>
</p:layout>
</h:body>
</html>
my ManagedBean:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import java.io.Serializable;
/**
*
* #author root
*/
#ManagedBean
#RequestScoped
public class HelloBean implements Serializable {
/**
* Creates a new instance of HelloBean
*/
private static final long serialVersionUID = 1L;
private String name="/main_pages/mainpage.xhtml";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
You need to use the <c:if test="condition"> tag around the ui:include and then when the ajax button is clicked, the panel that holds the ui:include is refreshed.
Example:
First make sure that the jstl core taglib is included by inserting the following namespace in the document:
<html xmlns:c="http://java.sun.com/jsp/jstl/core>"
Then, you can use the <c:if> tag as follows :
<c:if test="#{!logBean.loggedIn}">
<ui:include src="loginpage.xhtml" />
</c:if>
<c:if test="#{logBean.loggedIn}">
<ui:include src="home.xhtml" />
</c:if>

JSF 2.0 AJAX: jsf.ajax.request to call method not only rerender an area of page

I'm looking for a soultion of the following problem:
_The is a list of links with different types of cars.
_The user can click on each car in the list and a ajax request should be sent.
_The response of the ajax request should be dependent on the id (of each car) and displayed in an panelGroup.
So what I need is a possibility to call a method on the backing-bean. Additionally, this method should be called with a car id as its parameter.
My code so far looks like:
...
function showDetails(detailsFor){
jsf.ajax.request(this, event, {render: 'form1:carDetails'});
}
...
<ul>
<ui:repeat value="#{carTree.getCars)}" var="car">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<li onclick="showDetails(#{car.id});">#{car.name}</li>
</ui:repeat>
</ul>
...
<h:panelGroup id="carDetails" layout="block" style="float:left;">
// need the details of each 'selected /clicked' car here
</h:panelGroup>
...
And the method in the backing bean should look like:
public class CarTree {
...
public String getCarDetails(int carid){
return "The car details for the car id "+carid+" are......";
}
...
}
I've no idea how to call a method by using the new JSF 2.0 AJAX functionality. Please, help me...
Use f:setPropertyActionListener to pass a object from JSF page to your backend. This tag is especially useful when you are using repeatable components like datatable
No need to use raw JavaScript, you can use <f:ajax />. Plus instead of worrying about Car id and all, just send it completely to backing bean.
Here is a sample example:
The Car class:
public class Car {
int id;
String brand;
String color;
public Car(int id, String brand, String color) {
this.id = id;
this.brand = brand;
this.color = color;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
The CarTree class:
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean(name = "CarTree")
#RequestScoped
public class CarTree {
List<Car> carList;
Car selectedCar;
public Car getSelectedCar() {
return selectedCar;
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
public List<Car> getCars() {
return carList;
}
public void setCars(List<Car> carList) {
this.carList = carList;
}
public CarTree() {
carList = new ArrayList<Car>();
carList.add(new Car(1, "jaguar", "grey"));
carList.add(new Car(2, "ferari", "red"));
carList.add(new Car(3, "camri", "steel"));
}
}
The JSF page:
<?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:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body id="mainBody">
<h:form id="carForm">
<h:dataTable value="#{CarTree.cars}" var="car">
<h:column>
<h:outputText value="#{car.id}"/>
</h:column>
<h:column>
<h:outputText value="#{car.brand}"/>
</h:column>
<h:column>
<h:outputText value="#{car.color}"/>
</h:column>
<h:column>
<h:commandButton value="Show Car Detail" >
<f:setPropertyActionListener target="#{CarTree.selectedCar}" value="#{car}"/>
<f:ajax render=":carForm:carDetails" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:panelGroup id="carDetails" layout="block" style="float:left;">
<h:outputText value="#{CarTree.selectedCar.id}" />
<h:outputText value="#{CarTree.selectedCar.brand}" />
<h:outputText value="#{CarTree.selectedCar.color}" />
</h:panelGroup>
</h:form>
</h:body>
</html>
Hope this helps.
I haven't tested myself, but I'd suggest you try something like this (assuming your class CarTree is #Named and, therefore, can be referred to inside the JSF page using the name carTree):
<ul>
<ui:repeat value="#{carTree.getCars)}" var="car">
<li><h:commandLink action="#{carTree.getCarDetails(car.id)}" value="#{car.name}">
<f:ajax render="carDetails" />
</h:commandLink></li>
</ui:repeat>
</ul>
...
<h:panelGroup id="carDetails" layout="block" style="float:left;">
// need the details of each 'selected /clicked' car here
</h:panelGroup>
I think the contents of the action property in the <h:commandLink /> can also be coded as the listener property in the <f:ajax /> tag. Don't know if there's any difference...
If you don't want to use <h:commandLink /> you could replace it with <h:outputText /> and add the property event="click" to the <f:ajax /> tag. I think that would work as well. In this case, the method call would have to be in the listener property of the <f:ajax /> tag.

Resources