- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在将 JSF 与omnifaces 和cdi 一起使用。在 xhtml 页面中,我使用了一些类似于(下面的 jsf 页面有更多详细信息)
的 jswindow.onbeforeunload = function(e){
// some other stuff
return 'unsaved data';
};
如果窗口即将被卸载且仍有未保存的数据,则激活浏览器的默认确认对话框。
填写表单并重定向到同一页面,会弹出警告。如果我决定“留在页面上”,我将能够继续我的工作并随后提交我的表单,就像我预期的那样。
问题:如果我导航到其他页面或尝试关闭选项卡,警告也会按预期出现。但在本例中,提交“omnifaces.event: unload”的 http POST 会发送到服务器。据我所知,这会导致 Bean 的 onDestroy() 被调用。如果我选择留下来,表单中的所有值仍然存在于页面上,但是在提交表单时,会为这些值抛出 NPE(我猜是因为 bean 已经被销毁,不尊重我在确认对话框中的决定) .
经过几个小时的研究,我无法弄清楚为什么第二种情况会导致 Bean 卸载,而第一种方法会等待确认对话框的结果...有什么想法吗?
我已经注意到 window.onbeforeunload
应该用纯 js 调用,就像 ViewScoped 中提到的那样。这适用于第一种情况,但不适用于第二种情况。
编辑:
重现步骤位于 jsf 页面上。如果您遵循这些,您应该能够理解我的问题。
一些 bean
import org.omnifaces.cdi.ViewScoped;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Named;
import java.io.Serializable;
@Named
@ViewScoped
public class SomeBean implements Serializable {
private String fieldA;
private String fieldB;
private String info;
@PostConstruct
public void init(){
this.fieldA = null;
this.fieldB = null;
this.info = "bean = " + this;
}
@PreDestroy
public void preDestroy() {
/* triggered when performing a navigation to other resources or
closing the browser tab (unwanted), but not invoked if navigation is done
within the same resource, e.g by using templates and compositions (wanted) */
this.info = "destroy will be invoked for bean " + this;
}
public void submit(){
// do smth. with the fields
}
public String getFieldA() {
return fieldA;
}
public void setFieldA(String fieldA) {
this.fieldA = fieldA;
}
public String getFieldB() {
return fieldB;
}
public void setFieldB(String fieldB) {
this.fieldB = fieldB;
}
public String getInfo() {
return info;
}
public void setInfo(String info) {
this.info = info;
}
}
JSF 页面
<?xml version="1.0" encoding="UTF-8"?>
<!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:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui"
xml:lang="en" lang="en">
<h:head>
<title>reproduce example</title>
<script type="application/javascript">
$(document).ready(function () {
var unsavedData = false;
function setUnsavedData(flag) {
unsavedData = flag;
}
window.onbeforeunload = function (e) {
e = e || window.event;
if (unsavedData) {
if (e) {
e.preventDefault();
e.returnValue = 'Any string';
}
return 'Any string';
} else {
return undefined;
}
};
$(document).on("change", ":input:not(.stateless)", function () {
setUnsavedData(true);
});
$(document).on("click", "button.stateless", function () {
setUnsavedData(false);
});
});
</script>
</h:head>
<h:body>
<h:form id="myform">
<h3>steps to reproduce:</h3><br/>
1) enter some value for fieldA<br/>
2) click the 'navigate via navigationBean' link > confirm the dialog and 'stay on page'<br/>
3) press the submit button > as you can see, the bean instance is still the same and value is passed.<br/>
4) enter some value for fieldB<br/>
5) click somewhere else on the page to lose the input's focus (otherwise the confirm dialog won't show up!)<br/>
7) close the browser tab or use the browser's nav buttons > confirm the dialog and 'stay on page'<br/>
8) press the submit button again > as you can see now, submit has not been called! Pressing submit shows the bean instance has changed!<br/><br/>
<h4> > For this example, values are still usable after the new bean was initialized. Because the original page is way more complex then this example, <br/>
I really need to prevent onmnifaces from initializing a new bean, when a user confirms to stay on the page, even if he tries to close the tab!</h4><br/>
<br/>
fieldA
<p:inputText value="#{someBean.fieldA}"/>
<!-- note: in real code this is represented by a NavigationBean logic!-->
<p:commandLink value="navigate via navigationBean"
action="#"
ajax="false">
</p:commandLink>
<br/>
fieldB
<p:inputText value="#{someBean.fieldB}"/>
<br/>
<p:commandButton
id="submitBtn"
value="submit"
action="#{someBean.submit()}"
process="@form"
update="@form" styleClass="stateless">
</p:commandButton>
<br/>
<br/>
bean info: <p:outputLabel id="output_1" value="#{someBean.info}"/>
<br/>
value info for fieldA: <p:outputLabel id="output_2" value="#{someBean.fieldA}"/>
<br/>
value info for fieldB: <p:outputLabel id="output_3" value="#{someBean.fieldB}"/>
</h:form>
</h:body>
</html>
注意:这是一个最小化版本,原始版本有更多细节,但由于我们公司的一些限制,我无法显示完整的代码堆栈。我希望这仍然足够,并且在我看来,问题相关部分已显示。
Omnifaces 版本为 2.7
最佳答案
@ViewScoped
卸载脚本在 HTML <body>
末尾初始化。此时它将检查现有的 window.onbeforeunload
在装饰它之前先运行它。
您的window.onbeforeunload
函数在 $(document).ready()
期间定义。但这还没有在 HTML <body>
末尾执行。 。它仅在 <html>
结束后执行。因此@ViewScoped
卸载脚本将无法正确装饰它。
您需要确保 window.onbeforeunload
定义在@ViewScoped
之前卸载脚本已初始化。您可以通过将其放在外部来实现 $(document).ready()
并通过 <h:outputScript target="head">
导入包含定义的 JavaScript 文件或<h:outputScript target="body">
。将脚本内联放入 <head>
也可以,但不建议这样做,因为它只会让 HTML 文档变得更大,并且不会为浏览器提供缓存脚本的机会。
关于javascript - Omnifaces beforeunload 在某些情况下不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53176575/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!