使用jsf2.0ajax库调用一个方法
calling a method with jsf 2.0 ajax library
我正在开发一个应用程序,用户将在该应用程序中评估一件艺术品,并在进行过程中填写评审表。他们可能会在表单上花费大量时间,所以我想自动为用户保存,比如每5分钟保存一次。我希望我可以使用javascript并设置5分钟的计时器,然后让它通过ajax基本上执行整个表单,我可以将数据保存到数据库中,以防用户断开连接等。不幸的是,我似乎找不到任何方法来做到这一点。用数据更新模型不是问题,但我不知道如何让它调用方法(类似于提交时的操作)。我不想也不需要它重新呈现任何东西,只需要调用一个方法来保存数据。我该怎么做?
实施解决方案的问题
我尝试实现隐藏命令链接的解决方案,但我得到了一些非常奇怪的行为。我不确定是什么原因造成的。首先,介绍了实施的一些背景。Form#1创建一个bean(无作用域)并将其放入flash中,然后重定向到Form#2。Form#2是我写的一个大表单,我想在这里实现自动保存。表单#2有一个ViewScoped bean。在这个bean的PostConstruct中,它从flash中检索值,并填充一个属性字段。到目前为止还不错。这在没有javascript的情况下非常有效。我可以按命令按钮提交表格,一切都很好。然而,当我引入javascript时,当它执行时,我从变量中得到一个空指针异常,该变量本应由PostConstruct从flash中填充。这个javascript是如何干扰的?一旦我用对象填充了视图作用域bean的属性,它是否从flash作用域中删除应该无关紧要,对吧?仅供参考,如果我只删除javascript代码,并保留所有其他内容,当我按下按钮提交时,它会恢复正常工作。
表格#1
<h:form>
... bunch of form objects ...
<h:commandButton "Start New" action="#{someRequestScopedBean.someMethod"/>
</h:form>
someRequestScopedBean的代码。方法:
public String someMethod() {
// bunch of logic here
FacesContext.getCurrentInstance()
.getExternalContext()
.getFlash()
.put("myFlashObj", myFlashObj);
return "form2?faces-redirect=true";
}
表单2:中使用的视图范围bean
@ManagedBean
@ViewScoped
public class someViewScopedBean {
//bunch of properties here
@PostConstruct
public void initialize() {
this.myObject = (MyObject) FacesContext.getCurrentInstance()
.getExternalContext()
.getFlash()
.get("myFlashObject");
public void saveDraft() {
// save to database
}
}
表格2页码:
<h:outputScript library="javax.faces" name="jsf.js"/>
<h:form id="myForm">
... whole bunch of fields here ...
... real button for user to submit ...
<h:commandButton value="Submit myForm"
action="#{someViewScopedBean.save}" />
... hidden button for auto-save by javascript ...
<h:commandLink id="hiddenSaveDraft" style="display: none;"
action="#{someViewScopedBean.saveDraft}" >
<f:ajax execute="@form" />
</h:commandLink>
<script>
function saveDraft() {
document.getElementById('qForm:hiddenSaveDraft').onclick();
window.setTimeout('saveDraft()',15000);
}
saveDraft();
</script>
</h:form>
由于您写下了Javascript
作为标记之一,我将假设您在应用程序中包含客户端Javascript
代码。
首先使用隐藏的CCD_ 3或隐藏的<h:inputText/>
(在需要保存有关某个变量的一些信息的情况下,我使用后者)
在您提交的表格中添加以下内容之一:
<h:commandButton style="display:none" id="clickme">
<f:ajax execute="@form">
</h:commandButton>
<h:inputText style="display:none" id="changeme">
<f:ajax execute="@form">
</h:inputText>
在您的Javascript
代码中,添加此代码以单击或更改:
setInterval(function() {
document.getElementById("clickme").onclick();
}, 3000); // update every 3 seconds
setInterval(function() {
document.getElementById("changeme").onchange();
}, 3000); // update every 3 seconds
两者都会很好用。只要确保它们在您正在更新的表单中即可。
我找到了最终的解决方案,以及第一次实现时出现问题的原因。这与javascript何时被启动有关。脚本代码是在我放置<script></script>
块的确切位置激发的,那是在页面完全加载之前,可能是在DOM完成之前。这导致了各种恶劣的情况,包括@PostConstruct
的重复调用。
我通过使用javascript事件侦听器在页面完全加载时启动来修复它。这一点很重要,因为我使用的是facelets模板,并且我没有访问<h:body onload=
属性的权限。监听器是一个有用且优雅的解决方案。脚本块可以放置在页面中的任何位置。以下是脚本块的样子:
<script>
function saveDraft() {
document.getElementById('qForm:saveDraft').onclick();
window.setTimeout(saveDraft,300000);
}
function initSaveTimer(e) {
window.setTimeout(saveDraft,300000);
}
this.addEventListener("load",initSaveTimer,true);
</script>
这将每5分钟调用一次隐藏按钮来保存表单。
- 将一个方法转换为promise:Nodejs
- 如何在所有ng点击事件AngularJS上启动一个方法
- 创建一个方法,通过一个窗口进行迭代并获取Titanium中的所有控件
- 如何创建一个方法来验证数组的范围
- 如何将一个方法延迟到另一个方法首先完成,javascript
- 在Javascript中对类的每个实例调用一个方法
- 如何重写一个方法,并且仍然能够在重写的方法中使用基方法
- NodeJS-从同一文件中的另一个方法调用一个方法
- 有没有任何情况下,一个方法不应该是原型方法
- Jasmine间谍的函数称为一个方法
- 在带有参数列表的表单submit上调用一个方法
- 方法不在另一个方法内部调用
- 在 1 个方法中增加变量值会触发另一个方法的 for 循环,欢迎任何建议
- 如何使用javascript express node将变量从控制器中的一个方法公开.js到另一个控制器.js
- 如何在javascript中将变量的值分配给另一个方法
- 在浏览器关闭时,单击确认对话框中的“停留在页面上”,执行一个方法
- 使用一个方法在c#中启动其他方法
- 如何在Ember中转换到另一个路由时调用一个方法
- 在typescript中重载一个方法
- 我可以在setInterval函数中放入一个方法作为参数吗