I want to dynamically include .xhtml files at runtime, what you might call
the JSF front end to an inheritance hierarchy at the entity level. I expect
to have a total of 100 x 30-50 line xhtml files that would be loaded only
if required to correctly handle the underlying data. A typical use case is
that one or two xhtml files would be required to work on the underlying data,
so you can imagine that I don’t want to load the full 100 every time, it would
be criminally stupid to do so.
Now I know that there are endless discussions out there on this topic but
after countless hours of research I have got precisely nowhere. I am using
Mojarra 2.1.1.
In the example below I initially ui:include an ’empty’ file, a file with
minimal content (instead of c:catch), then click a commandButton which
changes the content to be included to new.xhtml and updates the container
of the ui:include with ajax.
The content of the new.xhtml is shown on the page, so this looks good. The
problem is that I’ve got a commandButton in new.xhtml, and when this file
is dynamically included the commandButton will not work – the action routine
is never called. If you use ui:include new.xhtml (instead of #{bean.page})
it works fine. So a few questions:
- Has anyone else got this working?
- If not is there another way of doing it?
- Why is something so incredibly obvious and useful so hard to do?
I had a play with jQuery load() today, and whilst I can load files using it
there are various issues. The files I want to load will contain PrimeFaces
dialogs and when loaded by jQuery the dialogs seemed to flash up momentarily
on the screen before disappearing, forever, into the abyss. Others report
components not having any css styling.
Thanks.
Edit: I should make it clear that my desire to do dynamic load rather than
simply navigating to a different page is because I just want to use
primefaces dialogs, a different one according to the type of underlying
data. It would be a neater way of doing it, if it’s possible.
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://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:commandButton value="push" action="#{bean.doit}">
<f:ajax render="load"/>
</h:commandButton>
<br/>
<h:panelGroup id="load">
<ui:include src="#{bean.page}"/>
<ui:remove>
<ui:include src="new.xhtml"/>
</ui:remove>
</h:panelGroup>
</h:form>
</h:body>
</html>
new.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:outputText value="new.xhtml"/>
<br/>
<h:commandButton value="inc" action="#{bean.inc}">
<f:ajax/>
</h:commandButton>
</html>
empty.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"/>
Bean.java
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Bean {
private String page = "/empty.xhtml";
public String doit() {
page = "/new.xhtml";
return null;
}
// getters & setters removed
}
The issue turns out to be that ui:include is implemented by a tag handler
which is executed during restore view and not re-executed during invoke
application, so when it modifies the component tree your application logic
is not aware of the changes. This is true only when using partial state
saving.
I copied the code from the ui:include tag handler into a very simple custom
component and could at least get action methods to fire, but not reliably.
The solution is to exclude views requiring this dynamic ui:include functionality
from using partial state saving with an entry in web.xml like this:
This has been tested with multiple commandButtons in multiple included page
fragments and seems to work reliably (tested with ViewScoped JSF beans). I’ve
also dynamically included a file containing a primefaces dialog and this works
ok as well. I hope this is of some use to others as it’s taken a good chunk of
time out of my schedule, but at least it’s working now, which is good.
Cheers.