Vaadin 14中按钮“ disableOnClick”的可靠性

问题描述

我正在使用Vaadin 14,为避免用户双击按钮而不是一次双击而多次发送请求,我在setdisableOnClick(true)实例上调用Button

对于某些按钮,这还不够:仍然可以多次单击按钮。在Chrome devtools中检查dom时,我看到为这些按钮设置了disableonclick属性

enter image description here

我怀疑这与事件处理程序的调用顺序有关(应该在要发送请求的处理程序之前调用要禁用的处理程序)。

我宁愿不在服务器端设置布尔值来检查操作是否已执行。单击后是否还有其他选项可以可靠地禁用按钮?

解决方法

这似乎是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,因此该代码将被跳过。

我看到三个选项:

  1. 重新连接按钮(重新打开对话框)后,通过反射将专用字段disableOnClickConfigured重置为false,然后再次调用setDisableOnClick(true)
  2. 复制代码以添加客户端事件监听器,并在重新连接按钮时执行它。
  3. 通过将按钮替换为新按钮,甚至在每次打开Dialog实例时都创建一个新的Dialog实例,可以避免此问题。

这是我选择使用的最后一个选项。 ObjectFactory是一个Spring bean,因此我正在使用Prototype范围并向其注入open,然后在调用split()之前获得一个新实例。