0

I'm trying to inject a Facelet into a portion my main page programmatically using FaceletContext#includeFacelet() (I can't use a <ui:include>) and after reading the answer to this question, I wrote the following code (it's a simple test case):

The view, index.xhtml:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:c="http://java.sun.com/jsp/jstl/core">
    <h:head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <title>Insert title here</title>
        <script src="JS/jquery-1.8.3.js" />
        <script type="text/javascript">
            $(function(){
                $('#mondiv').click(function(){
                    console.log("mondiv is clicked !");                     
                    includefacelet();
                });
            });
        </script>
    </h:head>
    <body>
        <h:form id="form1">
            <div id="mondiv" style="background-color: red; position: absolute; width: 20px; height: 20px;" />
            <p:remoteCommand name="includefacelet" actionListener="#{bean.includefacelet}" />
            <br /><br />
            <h:panelGroup id="pg" layout="block" style="background-   color:blue;position:absolute;width:200px;height:200px;" />
        </h:form>
    </body>
</html>

The managed bean:

package beans.a4jTests;

import java.io.IOException;

import javax.faces.application.Application;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.context.FacesContext;
import javax.faces.view.facelets.FaceletContext;

import org.primefaces.context.RequestContext;

@ManagedBean
@SessionScoped
public class Bean {

    public void includefacelet(){
        FacesContext fc = FacesContext.getCurrentInstance();
        UIForm form1 = (UIForm) fc.getViewRoot().findComponent("form1");
        HtmlPanelGroup pg = (HtmlPanelGroup) form1.findComponent("pg");
        FaceletContext faceletContext = (FaceletContext) fc.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);

        try {
            faceletContext.includeFacelet(pg, "NewFile.html");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //Refrsh
        RequestContext context = RequestContext.getCurrentInstance();         
        context.update("form1");
        context.update("pg");
        System.out.println("includefacelet is executed");
    }

}

The include, newfile.html:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!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">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
        <title>Insert title here</title>
    </head>
    <body>
        Hello ! this is the newfile.html
    </body>
</html>

I don't know why, not only nothing happens even the bean method was executed but also the bean method seems stopping to be executed for a second click and I didn't get any exception during the whole execution.

Community
  • 1
  • 1
Bardelman
  • 2,176
  • 7
  • 43
  • 70
  • @BalusC : After reading some documents, i ve a confusion about the meaning of Facelets : should i only add the Facelets templating structure in my page ? (a is used to work by itself without need to the whole templating structure though..) or i need to configure my whole application by adding javax.faces.DEFAULT_SUFFIX in the web.xml, the com.sun.facelets.FaceletViewHandler in the faces-config.xml and adding the jsf-facelets.jar to the library ? What is the optimal solution to make including facelets work please ? – Bardelman Apr 26 '13 at 15:47

1 Answers1

1

Call FaceletContext.includeFacelet() will not work, because that method is used by Facelets engine internally. It is not supposed users do that in that way. My advice is do not use FaceletContext inside managed beans.

Instead, in my opinion the best way to do it is use <ui:include src=#{someELPointingToTheTargetFacelet}/> . In that way facelets can know beforehand that the content is "dynamic" and take proper precautions.

In general, it is better to let facelets deal with component tree modifications through c:if, ui:include src="#{...}", c:choose and so on (but skip c:forEach).

lu4242
  • 2,318
  • 1
  • 15
  • 15
  • i know that it's not the most appropriate way but as i mentioned in my question i can't use because the injection should be made in a programmatically created UIHtmlPanelGroup. Also, is implemented as a tag handler and there is no corresponding UIComponent class so i can't also create it dynamically. i hope i can find a working example about what i want to achieve as it seems it have worked for example in the question i've referenced above. – Bardelman Apr 26 '13 at 19:21
  • I would try to avoid the step of create a component programatically at all. There are ways to do that, like do the inclusion into a facet and create a custom component that render the facet into its content. Currently there is no "official" way to include content generated by facelets programatically, and try to do that will be implementation specific. – lu4242 Apr 26 '13 at 19:49