1

I use a JSF 2.2, a Primefaces 6.0 and a CDI. One of my page includes a script which has got two javascript functions (one of them create a chart, second of them supply new data to the chart) and a simple form which works as a filter. I've cut my code (look at below) to show you the most important part of my code.

I would like to achieve something like this:

  • For the first time when the page is loaded/opened, the first javascript function should run (automatically without any pressing the button or the link) and should use several callback parameters which I set in the cdi bean.
  • Each time when I press the button, the second javascript function should run and should use several callback parameters which I set in the CDI bean.

How you see, the above mechanism is based on passing some values from the CDI bean to the javascript by means of the RequestContext. To achieve this I based on the primefaces documentation (chapter 11.1). So far, I've:

  • created several callback parameters for the first function in the init() method (which has the @PostConstruct annotation) of the CDI bean;
  • added the oncomplete attribute to the <p:commandButton> component which calls second of the function with args parameter. The values which I want to pass to the second function are prepared in actionFilterButton() method which I call in action attribute of the button.

At the moment my page works like this:

  • When the page is loaded/opened, the first javascript function isn't executed.
  • When I press the button, the second javascript function is executed and it saves the values of the callback parameters in the javascript variables.

How you see, the problem is the first stage. The first javascript function isn't executed when I open my page.

How can I call the first javascript function?

What did I try?

  • I tried to call the first javascript function on the server side calling requestContext.execute("firstFunction(args)"); in the init() method in hope it'll be worked but it isn't work and it breaks my form when I use the form. I'm not sure if I can put args as I did it on the server side (indeed I'm not sure if it is interpreted correctly).
  • I also tried to call firstFunction() at the end of my script (how you see below), but it isn't work as well.

My xhtml page:

<!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:ui="http://java.sun.com/jsf/facelets" 
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough"
xmlns:pe="http://primefaces.org/ui/extensions">

<h:head> 
    <!-- loading css -->
</h:head>

<h:body>

    <div id="container" style="height: 750px; width: 100%; margin: 0 auto;"/>

<script type="text/javascript">

    //<![CDATA[

    //Declaration of variables
    var chart;
    var data1;
    var data2;
    var data3;

    function firstFunction(args) {  

        $(function() {

            data1 = JSON.parse(args.data1);
            data2 = JSON.parse(args.data2);
            data3 = JSON.parse(args.data3);

            //Other operations          

        });
    }

    function secondFunction(args) {

        $(function() {

            data1 = JSON.parse(args.data1);
            data2 = JSON.parse(args.data2);
            data3 = JSON.parse(args.data3);

            //Other different operations            

        });
    }

    firstFunction(args);

    //]]>
</script>

<br/>

<h:form id="filterForm">

    <p:selectManyCheckbox id="filter" value="#{chart2Controller.selectedKindOfNetwork}" layout="responsive" columns="4">
        <p:ajax update="filterButton" />
        <f:selectItems value="#{chart2Controller.kindOfNetwork}" var="kindOfNetwork" itemLabel="#{kindOfNetwork}" itemValue="#{kindOfNetwork}" />
    </p:selectManyCheckbox>

    <br/>

    <p:commandButton id="filterButton" value="Filter" action="#{chart2Controller.actionFilterButton()}"
                    disabled="#{!chart2Controller.visibilityFilterButton}"
                    update="filterForm"
                    oncomplete="secondFunction(args);"/>    

</h:form>

</h:body>       
</html>                      

Part of my CDI bean:

@Named
@ViewScoped
public class Chart2Controller implements Serializable {

    /**
     * Start method.
     */
    @PostConstruct
    public void init() {

        initData();     

        //This isn't work.
        //requestContext.execute("firstFunction(args)");
    }

    /**
     * Downloading the data from the database.
     */
    private void initData(){


        /*
         * Sending the query to the database including the filter options of the form,
         * saving the result and preparing the data basing on the result.
         */

        //Preparing the callback parameters.
        requestContext = RequestContext.getCurrentInstance();
        requestContext.addCallbackParam("data1", data1);
        requestContext.addCallbackParam("data2", data2);
        requestContext.addCallbackParam("data3", data3);
    }

    /**
     * Action for the filter button.
     */
    public void actionFilterButton(){

        initData(); 
    }   

    /**
     * Visibility for filter button.
     */
    public boolean getVisibilityFilterButton(){     
        //return true or false.
    }   

    //Getter and Setter

    private static final long serialVersionUID = -8128862377479499815L;

    @Inject
    private VisualizationService visualizationService;

    private RequestContext requestContext;

    private List<ChartModel2> data;

    private List<String> kindOfNetwork;
    private List<String> selectedKindOfNetwork;

    private String data1;
    private String data2;
    private String data3;
}
4

2 回答 2

1

我相信把它包装成一个 IIFE 就可以了。如果您加载太快并且需要 dom,请尝试类似on load.

(function firstFunction(args) {  

    $(function() {

        data1 = JSON.parse(args.data1);
        data2 = JSON.parse(args.data2);
        data3 = JSON.parse(args.data3);

        //Other operations          

    });
})();
于 2016-07-21T20:28:30.593 回答
0

我刚刚找到了灵魂。确实有两种解决方案:在服务器端(我推荐)和在客户端。我的问题是这条 javascript 行:firstFunction(args);. 该args参数未正确解释。


在服务器端

首先,我更改了我的 javascript 函数的参数。args我使用了三个参数而不是参数(每个变量一个)。目前,脚本应如下所示:

<script type="text/javascript">

    //<![CDATA[

    //Declaration of variables
    var chart;
    var data1;
    var data2;
    var data3;

    function firstFunction(data1p, data2p, data3p) {    

        $(function() {

            data1 = JSON.parse(data1p);
            data2 = JSON.parse(data2p);
            data3 = JSON.parse(data3p);

            //Other operations          

        });
    }

    function secondFunction(data1p, data2p, data3p) {

        $(function() {

            data1 = JSON.parse(data1p);
            data2 = JSON.parse(data2p);
            data3 = JSON.parse(data3p);

            //Other different operations            

        });
    }

    //]]>
</script>

我也更改了oncomplete属性的值<p:commandButton>oncomplete="createChart(args.data1, args.data2, args.data3);"/>.

请注意,如果需要,您可以保留旧版本的第二个 javascript 函数(带有一个args参数)并保留旧版本的oncomplete属性。最重要的是第一个将在服务器端调用的 javascript 函数。

最后,我在 CDI beanrequestcontext.execute()的方法中调用了init()方法,所以我确信要下载的数据已经准备好了。

    /**
     * Start method.
     */
    @PostConstruct
    public void init() {

        initData();     

        requestContext.execute(String.format("createChart('%s', '%s', '%s')", getProtos(),getData(),getColors()));
    }

execute方法调用第一个 javascript 方法并传递三个必需的值。

请注意,我已经使用''字符在 javascript 端实现了正确的表示。


在客户端

在这种情况下,我只更改了第一个 javascript 函数。代替args参数,我使用了三个参数(每个变量一个),例如在前面的示例中。我保留了带有args参数的第二个函数,但如果您愿意,您可以按照与上一个示例相同的方式更改它。

最后,我在脚本末尾调用了第一个函数。看看下面的代码。我使用 EL 从 CDI bean 传递值。我还删除JSON.parse()了方法,因为 EL 直接写入了 javascript 代码,并且浏览器在我的案例中正确解释了数据。

<script type="text/javascript">

    //<![CDATA[

    //Declaration of variables
    var chart;
    var data1;
    var data2;
    var data3;

    function firstFunction(data1p, data2p, data3p) {    

        $(function() {

            data1 = data1p;
            data2 = data2p;
            data3 = data3p;

            //Other operations          

        });
    }

    function secondFunction(args) {

        $(function() {

            data1 = JSON.parse(args.data1);
            data2 = JSON.parse(args.data2);
            data3 = JSON.parse(args.data3);

            //Other different operations            

        });
    }

    firstFunction(#{chart2Controller.data1}, #{chart2Controller.data2}, #{chart2Controller.data3});

    //]]>
</script>
于 2016-07-21T22:56:41.443 回答