如何执行在服务器/客户端使用回调参数的javascript函数?

时间:2016-07-21 19:59:17

标签: javascript jsf primefaces requestcontext

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

我想实现这样的目标:

  • 第一次加载/打开页面时,第一个javascript函数应该运行(自动没有任何按下按钮或链接),并且应该使用我在cdi bean中设置的几个回调参数。
  • 每当我按下按钮时,第二个javascript函数应该运行,并且应该使用我在CDI bean中设置的几个回调参数。

您如何看待,上述机制基于通过RequestContext将一些值从CDI bean传递给javascript。为了达到这个目的,我基于主要的documentation(第11.1章)。到目前为止,我已经:

  • 为CDI bean的init()方法(具有@PostConstruct注释)中的第一个函数创建了几个回调参数;
  • oncomplete属性添加到<p:commandButton>组件,该组件使用args参数调用第二个函数。我想传递给第二个函数的值是用actionFilterButton()方法准备的,我在按钮的action属性中调用它。

目前,我的网页就像这样:

  • 加载/打开页面时,第一个javascript函数不会被执行。
  • 当我按下按钮时,会执行第二个javascript函数,它会将回调参数的值保存在javascript变量中。

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

如何调用第一个javascript函数?

我尝试了什么?

  • 我尝试在服务器端调用requestContext.execute("firstFunction(args)");方法中调用init()的第一个javascript函数,希望它能够正常工作,但它不起作用,它会破坏我的我使用表格时的表格。我不确定我是否可以在服务器端放置args(事实上我不确定它是否被正确解释)。
  • 我还尝试在脚本末尾调用firstFunction()(您将在下面看到),但它也不起作用。

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

2 个答案:

答案 0 :(得分: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          

    });
})();

答案 1 :(得分: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的{​​{1}}属性的值:<p:commandButton>

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

最后,我在CDI bean的oncomplete方法中调用了requestcontext.execute()方法,因此我确信将要下载的数据已准备就绪。

init()

/** * Start method. */ @PostConstruct public void init() { initData(); requestContext.execute(String.format("createChart('%s', '%s', '%s')", getProtos(),getData(),getColors())); } 方法调用第一个javascript方法并传递三个必需值。

请注意,我使用execute个字符来实现javascript端的正确表示。

在客户端

在这种情况下,我只更改了第一个javascript函数。我没有使用''参数,而是使用了三个参数(每个参数对应一个参数),例如前面的示例。我使用args参数保留了第二个函数,但是如果需要,可以像上一个示例一样更改它。

最后,我在脚本末尾调用了第一个函数。看下面的代码。我用EL来传递CDI bean的值。我还删除了args方法,因为EL直接写入javascript代码,浏览器正确解释了我的数据。

JSON.parse()