The technical Context
We are developing a J2E application with JSF 2.2 and IBM WAS 8.5.5.
The problem
We have developed a screen in order to load different forms (12 differents forms which include Ajax and other subform...). We want to be able to load dynamically the form in a modal box in Ajax using "ui:include" tag.
Unfortunately, the actions associated to those forms generated dynamically are not executed.
The questions
Do somebody had this problem earlier ?
Do you have some clue to solve the problem ?
Do you know an alternative to load dynamic forms in the same page ?
The code
We built a simple example showing the problem we have.
The main page (fragment)
<ui:composition template="/WEB-INF/templates/globalLayout.xhtml">
<ui:param name="context" value="publication"/>
<ui:define name="content">
<h:form>
<h:commandLink value="EDIT1"
action="#{test.edit()}" layout="block" >
</h:commandLink>
<h:commandLink value="EDIT2"
action="#{test.edit2()}" layout="block" >
</h:commandLink>
<ui:include src="#{test.page}"/>
</h:form>
</ui:define>
</ui:composition>
The subpage 1 (fragment)
<h:outputText value="Page 1 "></h:outputText>
<h:commandLink value="EDIT1" action="#{test.edit()}" layout="block" >
</h:commandLink>
<h:commandLink value="EDIT2" action="#{test.edit2()}" layout="block" >
</h:commandLink>
The subpage 2 (fragment)
<h:outputText value="Page 2 "></h:outputText>
<h:commandLink value="EDIT1" action="#{test.edit()}" layout="block" >
</h:commandLink>
<h:commandLink value="EDIT2" action="#{test.edit2()}" layout="block" >
</h:commandLink>
The managed Bean
package com.myapp;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "test")
#ViewScoped
public class TestManagedBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -3750906342500909173L;
private String page;
public void edit() {
page = "page.xhtml";
}
public void edit2() {
page = "page2.xhtml";
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
}
Note
Using the "ui:fragment" element is not useable. For us, it take nearly one minute to generated the page whereas with full ajax it should takes nearly 2,3 seconds.
So the example below is not working for us.
<ui:fragment rendered="#{index.page eq 'page2'}">
<ui:include src="page2.xhtml"/>
</ui:fragment>
Try using <ui:decorate template="#{test.page}"/> instead.
Related
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!
I found a strange behaviour regarding the ajax rendering of JSF and I am not shure what I am missing.
For simplicity I have a page with an h:inputText and and a h:panelGrid with a button inside. When someone clicks the button, the value of the h:inputText should be set with a standard value and the h:panelGrid should disappear. At first I will show the code then I explain it a bit more.
xhtml page:
<h:inputText id="trackingIdValue" value="#{bean.trackingId}" />
<h:panelGrid border="15" id="panel" rendered="#{not empty bean.list}">
<h:commandButton action="#{bean.render}" value="Clear Panel" >
<f:ajax execute="#this" render="panel trackingIdValue" />
</h:commandButton>
</h:panelGrid>
corresponding bean:
private Long trackingId;
private List<String> list;
public Long getTrackingId() {
return trackingId;
}
public List<String> getList() {
return list;
}
public void setList( List<String> list ) {
this.list = list;
}
#PostConstruct
public void init() {
// the list will be filled with some initial values
}
public void render() {
this.trackingId = 954643L;
list.clear();
}
When the page gets loaded the list will be filled with some values in the PostConstruct. This leads to the displaying of the panel because the list is not empty now. But when I click the button in the panel (where I change the trackingId and empty the list) the trackingId changed in the GUI but the panel is still visible. What did I do wrong?
UPDATE 1
As written in the comment I tried the code above in an empty project and there it works. I currently have a qiete huge application so shrinked down my pages and ended the following:
My project is consists of multiple page templates.In my master layout I have a h:head tag which loads many of my stylesheets I need for the application. When I completely remove the h:head tag then it works but then of course my styling is pretty bad. What does this has to do with my ajax loading and the panelgrid?
UPDATE 2
I have shorten my application to just one tiny page:
<h:head>
<h:outputStylesheet name="masterStyle.css" library="css" />
</h:head>
<h:body>
<h:form>
<h:inputText id="trackingIdValue" value="#{testBean.trackingId}" />
<h:panelGroup border="15" id="panel"
rendered="#{not empty testBean.list}">
<h:commandButton action="#{testBean.render}" value="Clear Panel">
<f:ajax execute="#this" render="panel trackingIdValue" />
</h:commandButton>
</h:panelGroup>
</h:form>
</h:body>
</html>
When I remove the header tag the ajax request works fine with both the inputtext and the panel. But when I add my stylesheets in the header like above ajax only works with the inputtext.
I'm trying to make registration with a few steps using JSF. Everything is based on f:ajax because page not have to be reloaded.
When i press "Show First Step" button the result appears. I'm pressing "SecondStep" button and second step appears. But when I press "ThirdStep" button everything disappears and I see no steps at all. There is no difference between "SecondStep" and "ThirdStep" buttons. I can't find out why this code doesn't work.
Here's html:
<aside class="block">
<h:form id="newform">
<h:commandButton value="Show First Step">
<f:ajax event="action" render="-allContent -firstStepForm" listener="#{stateBean.ajaxShowFirstStep}"></f:ajax>
</h:commandButton>
</h:form>
<h:panelGroup id="allContent">
<h:panelGroup id="firstStep">
<ui:fragment rendered="#{stateBean.firstStep}">
<span>AAAA</span>
<h:form id="firstStepForm">
<h:commandButton value="SecondStep">
<f:ajax event="action" render="-allContent -secondStepForm" listener="#{stateBean.ajaxShowSecondStep}"></f:ajax>
</h:commandButton>
</h:form>
</ui:fragment>
</h:panelGroup>
<h:panelGroup id="secondStep">
<ui:fragment rendered="#{stateBean.secondStep}">
<span>BBBB</span>
<h:form id="secondStepForm">
<h:commandButton value="ThirdStep">
<f:ajax event="action" render="-allContent -thirdStepForm" listener="#{stateBean.ajaxShowThirdStep}"></f:ajax>
</h:commandButton>
</h:form>
</ui:fragment>
</h:panelGroup>
<h:panelGroup id="thirdStep">
<ui:fragment rendered="#{stateBean.thirdStep}">
<span>CCCC</span>
<h:form id="thirdStepForm">
<h:commandButton value="Finish">
<f:ajax event="action" render="-allContent" listener="#{stateBean.ajaxShowFinish}"></f:ajax>
</h:commandButton>
</h:form>
</ui:fragment>
</h:panelGroup>
<h:panelGroup id="finish">
<ui:fragment rendered="#{stateBean.finish}">
<span>FINISH!!!</span>
</ui:fragment>
</h:panelGroup>
</h:panelGroup>
</aside>
And here's bean:
#ManagedBean(name = "stateBean")
#ViewScoped
#Getter
#Setter
public class StateSavingBean implements Serializable{
private static final long serialVersionUID = 5264945113749405548L;
private Boolean firstStep;
private Boolean secondStep;
private Boolean thirdStep;
private Boolean finish;
public StateSavingBean() {
}
public void ajaxShowFirstStep(AjaxBehaviorEvent event) {
setFirstStep(true);
setSecondStep(false);
setThirdStep(false);
setFinish(false);
}
public void ajaxShowSecondStep(AjaxBehaviorEvent event) {
setFirstStep(false);
setSecondStep(true);
setThirdStep(false);
setFinish(false);
}
public void ajaxShowThirdStep(AjaxBehaviorEvent event) {
setFirstStep(false);
setSecondStep(false);
setThirdStep(true);
setFinish(false);
}
public void ajaxShowFinish(AjaxBehaviorEvent event) {
setFirstStep(false);
setSecondStep(false);
setThirdStep(false);
setFinish(true);
}
}
If I'll remove "-allContent" from render attribute of f:ajax I'd be able to pass all the steps till Finish, but previous and next steps will not be hidden.
Please help me find the solution.
I'm using:
Server: JBoss Application Server 7.1,
JSF: javax.faces-2.2.0-20130214.084242-247.jar
Faces Config:
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
</faces-config>
Web Module: 3.0
Some answers:
Separator char was changed in web.xml:
<context-param>
<param-name>javax.faces.SEPARATOR_CHAR</param-name>
<param-value>-</param-value>
</context-param>
I tried without h:panelGroup id="allContent" and i was rendering only shown panelGroup that i want to hide and the next one I want to show. Result was the same.
I also was trying to use MyFaces 2.1.10, Mojarra 2.0.3-FCS and result was the same. BalusC wrote that it can be a bug that is fixed in JSF 2.2 but I still have this problem.
Hope someone will help me. Thank's!
I have this xhtml code:
<p:dataGrid id="dgData"
columns="1"
rows="100"
value="#{myStickiesController.items}"
var="sticky">
<p:panel header="From :#{sticky.users.displayName}" rendered="#{eventstickiesController.eventSticky}" binding="#{eventstickiesController.eventPanel}">
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
<h:panelGrid columns="2">
<p:graphicImage value="#{imageStreamer.fileContent}" style="width:50px; height: 50px" alt="No Profile Image">
<f:param id="uid" name="uid" value="#{sticky.users.userID}" />
</p:graphicImage>
<h:outputLabel value="Event Info : #{eventstickiesController.content}" binding="#{eventstickiesController.outputLabel}">
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
</h:outputLabel>
</h:panelGrid>
<f:facet name="footer">
<p:commandButton image="/images/buttons/Delete.gif"
actionListener="#{myStickiesController.deleteSticky}"
action="#{snippetsStickyEditorLinkerBean.updateSnippetLink}"
update="dgData" >
<f:attribute name="stickyId" value="#{sticky.stickyID}" ></f:attribute>
<f:param name="pageViewId" value="Default"/>
</p:commandButton>
</f:facet>
</p:panel>
</p:dataGrid>
the code of the actionListener class:
public class MyStickiesController {
public void deleteSticky(ActionEvent ae)
{
Long sid = (Long)ae.getComponent().getAttributes().get("stickyId");
Stickies s = ejbFacade.find(sid);
List<Recipients> rl = s.getRecipientsList();
DBConnectionProxyUser sbcpu = new DBConnectionProxyUser();
Users currentUser = sbcpu.getConnectedUser(ejbUsersFacade);
for (Recipients r:rl)
{
if (currentUser.getUserID()==r.getUsers().getUserID())
{
r.setDisplay(Boolean.FALSE);
}
}
}
}
Now, if I put the command button that is inside the p:dataGrid, the dataGrid is updated and the actionListener works. If I put the button inside the dataGrid, the dataGrid is not updated and the actionListener doesn't work.
I tried wrapping thw whole thing with p:outputPanel, and the actionListener doesn't work.
The ActionEvent is javax.faces.event.ActionEvent
I am using Mojarra 2.1.3 with primefaces 2.2.1, Glassfish 3.0.1 and Netbeans 6.9.1
Thanks in advance...
I managed to make it work...
The solution renders into 2 parts:
I updated the Glassfish Mojarra Module to 2.1.3
I added a p:remotecommamd and a p:outputpanel to be rendered in case the inner snippet is to be rendered. Other snippets are easy to be rendered.
I hope this one helps somebody...
I have found this topic, where's a bit of code to reload a div using Ajax.
I've tried creating such example, but not successfully.
Here's my code:
index.xhtml
<h:form>
<f:ajax render=":content">
<h:commandButton value="News" action="#{navigationBean.requestPage}">
<f:param name="requestedPage" value="news.xhtml"/>
</h:commandButton>
</f:ajax>
<br/><br/>
<f:ajax render=":content">
<h:commandButton value="News" action="#{navigationBean.requestPage}">
<f:param name="requestedPage" value="games.xhtml"/>
</h:commandButton>
</f:ajax>
</h:form>
</h:panelGroup>
<h:panelGroup id="content" layout="block">
<ui:include src="#{navigationBean.viewedPage}"/>
</h:panelGroup>
backing bean
#ManagedBean
#ViewScoped
public class NavigationBean
{
private String viewedPage;
public NavigationBean()
{
viewedPage = "news.xhtml";
}
public String getViewedPage()
{
return viewedPage;
}
public void setViewedPage(String viewedPage)
{
this.viewedPage = viewedPage;
}
public void requestPage()
{
Map<String,String> map = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
viewedPage = map.get("requestedPage");
}
}
how it looks:
So what am I missing? Variable viewedPage is updated, normal labels/texts etc. are updated, but can't get this div working.
Found the solution:
<h:commandButton value="Games" action="#{navigationBean.requestPage}">
<f:param name="requestedPage" value="games.xhtml"/>
<f:ajax execute="#this" render="#none" />
<f:ajax render=":content"/>
</h:commandButton>
plus changing #ViewScoped to #SessionScoped.