问题描述
我正在使用Vaadin 14,为避免用户双击按钮而不是一次双击而多次发送请求,我在setdisableOnClick(true)
实例上调用Button
。
对于某些按钮,这还不够:仍然可以多次单击按钮。在Chrome devtools中检查dom时,我看到为这些按钮设置了disableonclick
属性:
我怀疑这与事件处理程序的调用顺序有关(应该在要发送请求的处理程序之前调用要禁用的处理程序)。
我宁愿不在服务器端设置布尔值来检查操作是否已执行。单击后是否还有其他选项可以可靠地禁用按钮?
解决方法
这似乎是Vaadin错误。如果按钮位于Dialog
中的按钮先关闭然后重新打开,则该按钮不起作用。当您致电setDisableOnClick(true)
时,他们利用黑客手段从服务器端添加了事件监听器:
/**
* Initialize client side disabling so disabled if immediate on click even
* if server-side handling takes some time.
*/
private void initDisableOnClick() {
if (!disableOnClickConfigured) {
getElement().executeJs("var disableEvent = function () {"
+ "if($0.getAttribute('disableOnClick')){"
+ " $0.setAttribute('disabled','true');" + "}" + "};"
+ "$0.addEventListener('click',disableEvent)");
disableOnClickConfigured = true;
}
}
当按钮分离并重新连接时,该事件处理程序将消失。
不幸的是,重新打开对话框后再次调用setDisableOnClick(true)
将无济于事,因为disableOnClickConfigured
已被设置为true,因此该代码将被跳过。
我看到三个选项:
- 重新连接按钮(重新打开对话框)后,通过反射将专用字段
disableOnClickConfigured
重置为false
,然后再次调用setDisableOnClick(true)
。 - 复制代码以添加客户端事件监听器,并在重新连接按钮时执行它。
- 通过将按钮替换为新按钮,甚至在每次打开
Dialog
实例时都创建一个新的Dialog
实例,可以避免此问题。
这是我选择使用的最后一个选项。 ObjectFactory
是一个Spring bean,因此我正在使用Prototype范围并向其注入open
,然后在调用split()
之前获得一个新实例。