javascriptjsfprimefacesrequestcontext

Pass variable from bean to primefaces page


Another Primefaces Newbie here.

I want to pass data from a bean to XHTML page for use in javascript. Let me make it clear that the primefaces XHTML page does not have components so a normal binding like "#{bean.property}" is not in my requirement.

Is there a way to pass a bean variable to a page when the page is loaded and then to use it as a parameter in javascript.

As you can see I tried passing the "selectedProject" using the RequestContext but could not make it work. My scenario code:

Bean:

@Named(value = "ganttBean")
@SessionScoped
public class GanttBean implements Serializable {

@EJB
ProjectService projectService;
private Long selectedProjectId;
private Project selectedProject = null;

public GanttBean() {
}

public void init(){

    //get the actual project by ID.
    this.selectedProject = projectService.findById(selectedProjectId);
    //package all the tasks of the selected project in a JSON object
    jasonifyProject(selectedProject);

    RequestContext.getCurrentInstance().addCallbackParam("selectedProject",      selectedProject);
   //RequestContext.getCurrentInstance().execute("ggg()");
}

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">
<ui:composition template="../../WEB-INF/templates/master/default.xhtml"
            xmlns:ui="http://java.sun.com/jsf/facelets"
            xmlns:p="http://primefaces.org/ui"
            xmlns:h="http://java.sun.com/jsf/html"
            xmlns:f="http://java.sun.com/jsf/core"
            xmlns:em="http://java.sun.com/jsf/composite/ezcomp" 
            xmlns="http://www.w3.org/1999/xhtml">
  <ui:define name="content">
    <f:metadata>
        <f:viewParam name="projectId" value="#    {ganttBean.selectedProjectId}"/>
        <f:event type="preRenderView" listener="#{ganttBean.init()}"/>
    </f:metadata>
    <h1 class="title ui-widget-header ui-corner-all">
        Project Gantt View
    </h1>
    <h:outputScript library="jsGantt" name="jquery.1.8.js"/>
    <h:outputScript library="jsGantt" name="jquery-ui.min.js"/>
    <h:outputStylesheet library="jsGantt" name="jsgantt.css"/>
    <h:outputScript library="jsGantt" name="jsgantt.js" target="head"/>


    <div style="position:relative" class="gantt" id="GanttChartDIV">
        The gantt chart container

    </div>

    <script type="text/javascript">
     var ggg = function(datafrombean){
         ....do something with datafrombean....
     };

        //ionstantiate a gantt chart.
        var g = new    JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');


        //add tasks.
        g.AddTaskItem(new JSGantt.TaskItem(3,   'Define Chart API',       '2/10/2008','25/10/2008','000ff2', 'http://help.com', 0, 'Brian',     0, 1, 0,   1));
        g.AddTaskItem(new JSGantt.TaskItem(12,  'Chart Object',         '2/10/2008', '25/10/2008', 'ff00ff', 'http://www.yahoo.com', 0, 'Shlomy',  100, 0,3, 1));

        //draw the chart
        g.Draw();       
        g.DrawDependencies();

    </script>

    <h:form id="test">
        <h:inputHidden id="hiddenInput"  
                       value="hidden"/>

        <p:dialog id="editTaskDialog" widgetVar="editTaskDialog"   header="Edit Task">

    </p:dialog>
    </h:form>
</ui:define>
</ui:composition>

Solution

  • Well.... Let's think a little about how does it works.

    Javascript runs at the client side, purely front-end. JSF runs at the server side and render it's components to HTML, so it has the advantage to read the server-side properties, your bean, and then render the properties in the client side.

    So, a bridge between the server side and the front side is needed, which JSF already does.

    You claimed that your page does not have components, so a normal binding won't satisfy your requirements, but...what about an invisible component?

    JSF:

    <h:form id="formTest">
         <h:inputText style="display:none" id="idComp1" value="#{ganttBean.property}"></h:inputText>
    </h:form>
    

    JS:

    <script type="text/javascript">
     function(){
         var datafrombean = document.getElementById('formTest:idComp1').value 
     };
    </script>
    

    I'm not sure how many times and when you want to call that function, but you may have to use ajax to render again the invisible component and then call the JS function again.

    Also, I'm sure that there is other simple options, it is just an way to do that