java JSF a4j:设置“禁用”时命令按钮不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2193741/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 19:58:37  来源:igfitidea点击:

JSF a4j:commandButton not working when 'disabled' is set

javajsfjakarta-eerichfacesajax4jsf

提问by Jon Onstott

When I include a 'disabled' attribute on an a4j:commandButton, the button's action is not performed. Taking the 'disabled' attribute out causes it to work properly. I am not doing any special validation (that I'm aware of) and am not seeing any validation error messages.

当我在 a4j:commandButton 上包含“禁用”属性时,不会执行按钮的操作。去掉 'disabled' 属性会使其正常工作。我没有做任何特殊的验证(我知道),也没有看到任何验证错误消息。

Here is part of my page:

这是我的页面的一部分:

<t:dataTable id="myTable"
             var="region"
             value="#{MyPageBackingBean.regions}"
             width="100%">

...

<a4j:commandButton value="Update"
                   action="#{region.doUpdate}"
                   oncomplete="alert('done');"
                   disabled="#{!empty region && region.messageEmpty}"
                   immediate="true"/>

...

</t:dataTable>

Any ideas? Thanks!

有任何想法吗?谢谢!

Edit:

编辑:

I tried setting preserveDataModel="true" on the t:dataTable to no avail.

我尝试在 t:dataTable 上设置 preserveDataModel="true" 无济于事。

I also made a test having an a4j:commandButton and text box with no data table, but the backing bean action is still not being fired:

我还做了一个测试,有一个 a4j:commandButton 和没有数据表的文本框,但仍然没有触发支持 bean 操作:

      <h:form>
     <a4j:region>
        <a4j:outputPanel id="testregion">
        <h:messages id="messages"/>

                          <a4j:status>
                             <f:facet name="start">
                                <h:graphicImage value="/images/progress_indicator.gif"/>
                             </f:facet>
                          </a4j:status>

                       <h:inputTextarea
                             rows="5"
                             value="#{MyPageBackingBean.myValue}"
                             style="width:100%; border: 1px solid #99CCFF;">
                          <a4j:support event="onkeyup"
                                       reRender="testregion"
                                       eventsQueue="messageModificationQueue"
                                       ignoreDupResponses="true"
                                       requestDelay="500"/>
                       </h:inputTextarea>

                       <a4j:commandButton id="doDelete"
                                          value="Delete"
                                          action="#{MyPageBackingBean.dummy}"
                                          reRender="testregion"
                                          disabled="#{empty MyPageBackingBean.myValue}"/>
                    <h:outputText value="#{MyPageBackingBean.myValue}"/>
        </a4j:outputPanel>
     </a4j:region>
  </h:form>

Here is the new backing bean code used for testing:

这是用于测试的新支持 bean 代码:

private String m_myValue = null;
   public String getMyValue()
   {
      return m_myValue;
   }
   public void setMyValue(String value)
   {
      m_myValue = value;
   }
   private String mystr2 = null;
   public String dummy()
   {
      mystr2 = "hello";
      return null;
   }

Thanks!

谢谢!

回答by BalusC

In HTML world, the disabledattribute causes the name-valueattribute pair of any HTML input element (input, select, textareaand button) not being sent to the server side.

在 HTML 世界中,该disabled属性会导致任何 HTML 输入元素(、、和)的name-value属性对不会被发送到服务器端。inputselecttextareabutton

In JSF world, the presense of the nameattribute is been used to identify the bean action to be invoked at the server side. However, during apply request values phase of the form submit JSF also checks if the component's disabled(and rendered) attribtue evaluates truebefore taking any actions.

在 JSF 世界中,name属性的存在用于标识要在服务器端调用的 bean 操作。但是,在表单提交的应用请求值阶段,JSF 还会在采取任何操作之前检查组件的disabled(和rendered)属性是否评估true

The #{region}is here an iterated table row object of #{MyPageBackingBean.regions}whose isMessageEmpty()getter by default returns true. In the new request of the form submit the #{MyPageBackingBean.regions}is apparently empty which effectlively makes the button disabled. JSF won't invoke the associated action then.

这里#{region}是一个迭代表行对象,#{MyPageBackingBean.regions}isMessageEmpty()getter 默认返回true。在表单提交的新请求中,#{MyPageBackingBean.regions}显然是空的,这有效地使按钮变得生动disabled。然后 JSF 不会调用关联的操作。

To the point, you need to make sure that #{MyPageBackingBean.regions}returns exactly the same datamodel in the subsequent request. Easiest fix is to place the MyPageBackingBeanbean in session scope so that it don't get reinitialized in the subsequent request, but that has more negative side effects as well. Another fix is to rearrange the datamodel loading so that it happens in the bean constructor. As you're already using Tomahawk's <t:dataTable>, you need to set its preserveDataModelattribute to true. For more hints about using datatables, you may find this article useful as well: Using Datatables.

就此而言,您需要确保#{MyPageBackingBean.regions}在后续请求中返回完全相同的数据模型。最简单的解决方法是将MyPageBackingBeanbean 放在会话范围内,这样它就不会在后续请求中重新初始化,但这也会产生更多负面影响。另一个修复是重新安排数据模型加载,以便它发生在 bean 构造函数中。由于您已经在使用 Tomahawk 的<t:dataTable>,您需要将其preserveDataModel属性设置为true。有关使用数据表的更多提示,您可能会发现这篇文章也很有用:使用数据表

回答by drteeth

One other thing to note about the disabled property for an a4j:commandButton: if the disabled property is set to true, then the ajax hook for the button's onclick event is never rendered into the final HTML. That is, you get a button like this:

关于 a4j:commandButton 的 disabled 属性要注意的另一件事:如果 disabled 属性设置为 true,则按钮的 onclick 事件的 ajax 钩子永远不会呈现到最终的 HTML 中。也就是说,你会得到一个这样的按钮:

<input type="button" onclick="return false" ... />

instead of this:

而不是这个:

<input type="button" onclick="A4J.AJAX.Submit('....');return false" ... />

So, if you want to do something like this:

所以,如果你想做这样的事情:

  1. Render page with disabled a4j:button
  2. Enable a4j:button on client side based on user interaction
  3. Click on a4j:button to call server side action
  1. 渲染页面禁用 a4j:button
  2. 根据用户交互在客户端启用 a4j:button
  3. 单击 a4j:button 调用服务器端操作

Then you will instead need to do something like this:

然后你将需要做这样的事情:

  1. Render page with a4j:button and disabled="#{true}"
  2. Have the user interaction trigger a re-render of the a4j:button with disabled="#{false}"
  3. Click on the a4j:button to call the server side action
  1. 使用 a4j:button 和 disabled="#{true}" 呈现页面
  2. 让用户交互触发 a4j:button with disabled="#{false}" 的重新渲染
  3. 点击 a4j:button 调用服务器端动作

Here's a simple example:

这是一个简单的例子:

<h:selectOneCheckbox value="#{myAction.booleanProperty}">
  <a4j:support event="onclick" reRender="button1" />
</h:selectOneCheckbox>
<a4j:commandButton id="button1" action="#{myAction.doSomething}" 
  disabled="#{myAction.booleanProperty eq false}" value="click me"
/>