如何在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 函数(其中一个创建图表,第二个为图表提供新数据)和一个用作过滤器的简单表单。我已经剪切了我的代码(请看下面)以向您展示我代码中最重要的部分。
我想实现这样的目标:
- 第一次当页面是 loaded/opened 时,第一个 javascript 函数应该 运行(自动不按任何按钮或 link)并且应该使用我在 cdi bean 中设置的几个回调参数。
- 每次我按下按钮时,第二个 javascript 函数应该 运行 并且应该使用我在 CDI bean 中设置的几个回调参数。
如您所见,上述机制是基于通过 RequestContext
将一些值从 CDI bean 传递到 javascript。为此,我基于 primefaces documentation(第 11.1 章)。到目前为止,我已经:
- 为 CDI bean 的
init()
方法(具有 @PostConstruct
注释)中的第一个函数创建了几个回调参数;
- 将
oncomplete
属性添加到 <p:commandButton>
组件,该组件使用 args
参数调用第二个函数。我想传递给第二个函数的值是在 actionFilterButton()
方法中准备的,我在按钮的 action
属性中调用了该方法。
目前我的页面是这样的:
- 当页面为 loaded/opened 时,不执行第一个 javascript 函数。
- 当我按下按钮时,第二个 javascript 函数被执行并将回调参数的值保存在 javascript 变量中。
你怎么看,问题出在第一阶段。当我打开我的页面时,第一个 javascript 函数没有执行。
如何调用第一个javascript函数?
我尝试了什么?
- 我尝试在服务器端调用第一个 javascript 函数,在
init()
方法中调用 requestContext.execute("firstFunction(args)");
希望它能工作,但它不工作而且它当我使用表格时破坏了我的表格。我不确定我是否可以像在服务器端那样放置 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;
}
我相信将它包装成 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>
我使用 JSF 2.2、Primefaces 6.0 和 CDI。我的一个页面包含一个脚本,该脚本具有两个 javascript 函数(其中一个创建图表,第二个为图表提供新数据)和一个用作过滤器的简单表单。我已经剪切了我的代码(请看下面)以向您展示我代码中最重要的部分。
我想实现这样的目标:
- 第一次当页面是 loaded/opened 时,第一个 javascript 函数应该 运行(自动不按任何按钮或 link)并且应该使用我在 cdi bean 中设置的几个回调参数。
- 每次我按下按钮时,第二个 javascript 函数应该 运行 并且应该使用我在 CDI bean 中设置的几个回调参数。
如您所见,上述机制是基于通过 RequestContext
将一些值从 CDI bean 传递到 javascript。为此,我基于 primefaces documentation(第 11.1 章)。到目前为止,我已经:
- 为 CDI bean 的
init()
方法(具有@PostConstruct
注释)中的第一个函数创建了几个回调参数; - 将
oncomplete
属性添加到<p:commandButton>
组件,该组件使用args
参数调用第二个函数。我想传递给第二个函数的值是在actionFilterButton()
方法中准备的,我在按钮的action
属性中调用了该方法。
目前我的页面是这样的:
- 当页面为 loaded/opened 时,不执行第一个 javascript 函数。
- 当我按下按钮时,第二个 javascript 函数被执行并将回调参数的值保存在 javascript 变量中。
你怎么看,问题出在第一阶段。当我打开我的页面时,第一个 javascript 函数没有执行。
如何调用第一个javascript函数?
我尝试了什么?
- 我尝试在服务器端调用第一个 javascript 函数,在
init()
方法中调用requestContext.execute("firstFunction(args)");
希望它能工作,但它不工作而且它当我使用表格时破坏了我的表格。我不确定我是否可以像在服务器端那样放置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;
}
我相信将它包装成 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>