如何在server/client端执行使用回调参数的javascript函数?

How to execute javascript function which uses the callback parameters on the server/client side?

我使用 JSF 2.2、Primefaces 6.0 和 CDI。我的一个页面包含一个脚本,该脚本具有两个 javascript 函数(其中一个创建图表,第二个为图表提供新数据)和一个用作过滤器的简单表单。我已经剪切了我的代码(请看下面)以向您展示我代码中最重要的部分。

我想实现这样的目标:

如您所见,上述机制是基于通过 RequestContext 将一些值从 CDI bean 传递到 javascript。为此,我基于 primefaces documentation(第 11.1 章)。到目前为止,我已经:

目前我的页面是这样的:

你怎么看,问题出在第一阶段。当我打开我的页面时,第一个 javascript 函数没有执行。

如何调用第一个javascript函数?

我尝试了什么?

我的 xhtml 页面:

<!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>                      

我的 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;
}

我相信将它包装成 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          

    });
})();

我刚刚找到灵魂。确实有两种解决方案:在服务器端(我推荐)和在客户端。我的问题是 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>

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

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

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

    /**
     * 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>