3

我有一个简单的脚本标签,其中包含一个包含在 html 正文底部的函数。此脚本只是禁用提交按钮。然后我有一个onclick调用该函数的事件。

我在 5 个不同的页面中有此代码,它适用于五个页面中的三个。

这是代码:

<!-- more non-important html -->

<h:commandButton id="buttonToDisable" 
    value="some text"
    action="#{myBean.myBeansAction}" 
    actionListener="#{myBean.myBeansActionListener}" 
    onclick="disableButton()">

    <!-- I also have an f:param in some of these pages but I didn't 
    think that would matter -->

</h:commandButton>

<!--  more non-important html -->

<script>
    function disabledButton() {
        document.getElementById("myForm:buttonToDisable").disabled = 'true';
    }
</script>

任何帮助将不胜感激。有效和无效的页面之间的唯一区别是actionactionListeners是不同类型的 bean,有些有f:params,有些没有。

4

3 回答 3

7

我了解您的具体问题是,一旦禁用按钮,就不会调用支持 bean 的操作?这可能是非常真实的。JSF 根据与组件的 HTML 表示相关联的请求参数名称的存在来确定要调用的操作UICommand。但是,当禁用 HTML 输入/按钮元素时,它的 name=value 将根本不会作为请求参数发送(因此 JSF 将无法确定要调用的操作)。onclick即在发送表单提交请求之前调用该属性。

您想在表单提交请求发送到服务器端后禁用该按钮。到目前为止给出的代码,唯一的方法是button.disabled=true在约 50 毫秒的超时后调用。

<h:commandButton ... onclick="setTimeout('document.getElementById(\'' + this.id + '\').disabled=true;', 50);" />

但是,如果您使用的是 JSF 2.0 <f:ajax>,那么还有另一种更强大和更全球化的方式:

function handleDisableButton(data) {
    if (data.source.type != "submit") {
        return;
    }

    switch (data.status) {
        case "begin":
            data.source.disabled = true;
            break;
        case "complete":
            data.source.disabled = false;
            break;
    }    
}

jsf.ajax.addOnEvent(handleDisableButton);

在对您有用的情况下,该按钮很可能是启用了 ajax 的按钮。事先禁用该按钮没有副作用。

于 2012-07-31T18:42:52.463 回答
6

您应该在单击事件之后从服务器端 actionListener 设置 commandButton 组件的启用状态。

<h:commandButton disabled="#{managedBean.someBooleanPropertyThatWasToggledInTheEvent}" />

您可以在调用服务器端事件后简单地设置托管属性,它将在页面刷新时被禁用。

更新:

我刚刚意识到 OP 有一个完全不同的问题。用户不耐烦并单击按钮而不是等待回发。然而,禁用命令按钮有时会阻止调用服务器端操作。

解决这个问题的正确方法是在页面上放置一个绝对位置的 div 覆盖,其 z-index 比页面上的任何其他元素都高。这将防止在覆盖 div 之外的任何内容上发生进一步的点击。这是一个例子:

CSS 样式

.div-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: #000;
    filter:alpha(opacity=50);
    -moz-opacity:0.5;
    -khtml-opacity: 0.5;
    opacity: 0.5;
    z-index: 10000;
}

利用 jQuery fadeToggle 功能的 Javascript 切换功能

function toggleLoadingOverlay() {
  var div = jQuery('.div-overlay');
  div.fadeToggle(150);
}

** JSF commandButton onclick 事件,一旦单击按钮就会发生(并假设事件传播没有被中断)**

<h:commandButton onclick="toggleLoadingOverlay();" action="..." />
于 2012-07-31T17:20:22.873 回答
0

我尝试了@maple_shaft 建议的解决方案,但 opaque/toggleFade() div总是吸收击键,即使它是 opacity=0。这是我的答案:

<script type="text/javascript">
    function overlayToFront()
    {
        document.getElementById("div-overlay").style.zIndex = "10000";
    }
</script>

页:

<... id="form1"> <!-- in the existing code, some component with id="form1" in my case it was a:form -->
    <div id="div-overlay" 
        style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #000;
            filter:alpha(opacity=0); -moz-opacity:0.0; -khtml-opacity: 0.0; opacity: 0.0;
            z-index: -10000; cursor: wait;">
        <!-- lay out a transparent div in the background.
        Buttons with onclick="overlayToFront();" can prevent double-clicks by covering the whole GUI when this div gets moved to the front
        Currently only used in one place, but any button with reRender="form1" should be able to to this
        -->
    </div>
    <div id="div-base-layer"
        style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #000;
            filter:alpha(opacity=0); -moz-opacity:0.0; -khtml-opacity: 0.0; opacity: 0.0;
            z-index: -1;" > <!-- rendered "on top of" div-overlay, so cursor does not change when moving off the legacy part of the page -->
    </div>
    <div>
        <!-- this is where the legacy part of the page, the contents of the component with id="form1" goes. it did not have a position: attribute in the original code so z-index does not affect it -->
    </div>
</ ...> <!-- end of tag with id="form1"  -->
于 2017-04-05T20:05:49.043 回答