如何重置 p:dialog 以及所包含组件的禁用状态?

How to reset p:dialog together with the disable-state of the contained components?

Primefaces 4.0

我需要重置 p:dialog 中包含的组件的初始禁用状态。 以下简化示例显示了问题:

XML:

<p:dialog header="header" widgetVar="dialog" appendTo="@(body)"
          modal="true" resizable="false">
    <h:form id="form">
         <p:inputText value="#{bean.text}" id="text" />
         <p:commandButton value="Disable InputText" 
                          action="#{bean.disableInputText}" />
         <p:commandButton value="Cancel"
                                 action="#{bean.cancelDialog}"
                                 process="@this"
                                 update="@form" immediate="true">
            <p:resetInput target="@form"/>
        </p:commandButton>
    </h:form>
 </p:dialog>

ManagedBean:

 @ViewScoped
 public class Bean {
      public void disableText() {
         final FacesContext context = FacesContext.getCurrentInstance();
         final UIViewRoot root = context.getViewRoot();
         final UIComponent component = root.findComponent(":text");
         if (uiComponent instanceof InputText) {
             ((InputText) uiComponent).setDisabled(true);
         }
      }

      public void cancel() {
           // reset disable-state of the disable-state of all components in a generic way.
      }
 }

使用对话框时,可以禁用 p:inputText 元素。如果对话框被取消并再次打开,则不应禁用 inputText。应该已经恢复到初始状态了。请注意,这个例子是简化的,我正在寻找一个通用的解决方案,它也适用于具有 10 个以上输入元素的公式。

通用(也是最广泛的)解决方案

对于通用解决方案,您可以使用 Java Server Faces 中提供的状态保存功能。使用您的代码示例作为基础(进行一些小的更改以清理内容),这是一个使用状态保存并恢复组件先前状态的示例;

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.org/ui">
    <h:head>
        <title>Disable Test</title>
    </h:head>
    <h:body>

        <p:dialog  header="header" widgetVar="dialog" appendTo="@(body)" modal="true" resizable="false">
            <h:form id="form">
                <p:inputText value="#{disableTestBean.text}" id="text"/>
                <p:commandButton value="Disable InputText" action="#{disableTestBean.onDisable}" update="@form" />
                <p:commandButton value="Cancel" action="#{disableTestBean.onCancel}" update="@form" onsuccess="PF('dialog').hide()" />
            </h:form>
        </p:dialog>
        <button onclick="PF('dialog').show()">Open</button>
    </h:body>
</html>

要真正看到重置发生,从第二个 commandButton 中删除 onsuccess 属性 - 因为它当前关闭对话框。

@Data
@Named
@ViewScoped
public class DisableTestBean implements Serializable {
    private String text;
    private Object prevState;

    private UIComponent findComponent(String where) {
        final FacesContext context = FacesContext.getCurrentInstance();
        final UIViewRoot root = context.getViewRoot();
        return (UIComponent) root.findComponent(where);
    }

    public void onDisable() {
        final InputText component = (InputText) findComponent(":form:text");
        component.setDisabled(false);
        component.setValue("");

        prevState = component.saveState(FacesContext.getCurrentInstance());
        component.setValue("meh");
        component.setDisabled(true);
    }

    public void onCancel() throws IOException {
        final InputText component = (InputText) findComponent(":form:text");
        component.restoreState(FacesContext.getCurrentInstance(), prevState);
    }
}

该示例针对一个特定的输入组件。但是,如果你需要处理多个组件,你可以很容易地使用一个循环来以通用的方式完成你想要的。

作为演示,我不仅重置了上面支持 bean 中的禁用状态,还重置了输入组件的值(内容)。这向您展示了如何实际重置组件的完整状态(不仅是单个属性或值)。所以解决方案很广泛,也很通用。

第二种更直接的方法

第二种方法是做 @Kukeltje 在他上面的评论中暗示的事情。在输入组件上使用 disabled= 属性,并有一个支持 bean 值,当您按 Cancel 时,该值只会将值更改为 false。这不是一般的,不会适用于其他一切,但它会在您的特定用例中完成工作。如果您只对禁用状态感兴趣,它甚至可能是首选的方式。如果你也想要一个例子,我可以扩展这个答案 - 告诉我。