在PrimeFaces中使用Ajax事件时重置Bean

问题描述:

我有一个对话框,其中包含复选框和一个输入字段。当这个复选框被选中时,输入应该被禁用。复选框值存储在Bean中,输入值是所选对象值之一。在PrimeFaces中使用Ajax事件时重置Bean

当用户点击列表上的链接时,弹出此对话框。 Dialog的输入正在使用模型中的值填充。

我也有两个按钮:保存和取消。在保存时,根据复选框的值,我对模型做了不同的事情并更新它。在取消我想什么都不做。

问题是:当有Ajax事件与复选框连接时,Bean中的值会自动更新。因此,点击取消并重新打开对话框后,我得到了最后一个状态,但我想要初始状态。

下面是代码:

列表

<h:form id="termPanelForm"> 

    <p:dataTable id="termPanelTable" 
     value="#{termRightPanelController.terms}" var="term" emptyMessage=""> 

     <p:column> 
      <p:commandLink value="#{term.subject}" 
       action="#{termRightPanelController.setTerm(term)}" 
       oncomplete="termRealizeDlg.show();" 
       update=":termRealizeForm:termRealizeDialog" /> 
     </p:column> 

     <p:column width="50"> 
      <h:outputText value="#{term.dateRealization}"> 
       <f:convertDateTime pattern="dd-MM-yy HH:mm" /> 
      </h:outputText> 
     </p:column> 
    </p:dataTable> 

</h:form> 

对话框

<h:form id="termRealizeForm"> 
    <p:dialog id="termRealizeDialog" widgetVar="termRealizeDlg" 
     modal="true" resizable="false" closeOnEscape="true" 
     header="#{termRightPanelController.selectedTerm.subject}"> 

     <p:messages autoUpdate="true" showDetail="true"></p:messages> 

     <p:panelGrid columns="2" styleClass="border-none"> 

      <p:outputLabel for="realized" value="#{i18n['Term.MarkRealized']}" /> 
      <p:selectBooleanCheckbox id="realized" 
       value="#{termRightPanelController.termRealized}"> 
       <p:ajax process="@this" update="dateRealization" /> 
      </p:selectBooleanCheckbox> 

      <p:outputLabel for="dateRealization" 
       value="#{i18n['Term.ChangeDateRealization']}" /> 
      <p:inputText id="dateRealization" 
       value="#{termRightPanelController.selectedTerm.dateRealization}" 
       pattern="dd-MM-yyyy HH:mm" 
       disabled="#{termRightPanelController.termRealized}" > 
      </p:inputText> 

     </p:panelGrid> 

     <h:panelGroup layout="block" styleClass="buttons-group"> 
      <p:commandButton value="#{i18n['Common.Save']}" 
       oncomplete="hideDialogWhenValid(termRealizeDlg, xhr, status, args);" 
       action="#{termRightPanelController.editTerm()}" 
       update=":termPanelForm:termPanelTable" icon="ui-icon-check"></p:commandButton> 
      <p:commandButton onclick="termRealizeDlg.hide();" 
       value="#{i18n['Common.cancel']}" 
       icon="ui-icon-cancel" update=":termRealizeForm:termRealizeDialog"> 
      </p:commandButton> 
     </h:panelGroup> 

    </p:dialog> 
</h:form> 

@SuppressWarnings("rawtypes") 
@ManagedBean 
@ViewScoped 
public class TermRightPanelController extends MainController implements Serializable { 

    private static final long serialVersionUID = 6283828584670862366L; 

    private TermServiceLocal termService = ServiceLocator.locateService(
      TermService.class, TermServiceLocal.class); 

    private List<Term> terms; 

    private Term selectedTerm; 

    private boolean termRealized; 

    @PostConstruct 
    public void init() { 
     loadTerms(); 
    } 

    public void loadTerms() { 
     terms = termService.getTermsNotRealized(getLoggedUser().getId()); 
    } 

    public String expiredTerm(Term term) { 
     long time = new Date().getTime(); 
     if (term.getDateRealization().getTime() > time) { 
      return ""; 
     } 

     return "expired"; 
    } 

    public void editTerm() { 
     if (termRealized) { 
      selectedTerm.setDateRead(new Date()); 
     } else { 
      selectedTerm.setDateRead(null); 
     } 
     termService.merge(selectedTerm); 
     loadTerms(); 
    } 

    public void setTerm(Term term) { 
     this.selectedTerm = term; 
    } 

    public List<Term> getTerms() { 
     return terms; 
    } 

    public void setTerms(List<Term> terms) { 
     this.terms = terms; 
    } 

    public Term getSelectedTerm() { 
     return selectedTerm; 
    } 

    public void setSelectedTerm(Term selectedTerm) { 
     this.selectedTerm = selectedTerm; 
    } 

    public boolean isTermRealized() { 
     return termRealized; 
    } 

    public void setTermRealized(boolean termRealized) { 
     this.termRealized = termRealized; 
    } 

    @Override 
    public Class getModelClass() { 
     return this.getClass(); 
    } 
} 

在这种特殊情况下,当我单击取消时,总是可以将termRealized设置为false,但在其他场景中,我已从模型中加载值。所以重新打开对话框后,我想要有与模型中相同的值,而不是由Bean存储。

我们已经讨论了球队的一些可能的解决方案,但对我们来说,似乎都讨厌:

  1. 我们可以在特定克隆selectedTerm和克隆重新加载它取消。这是令人讨厌的,因为我们需要在我们想要编辑的每个元素上实现可克隆的接口。
  2. 我们可以编写自定义JavaScript来处理禁用的事件和其他事件。但是我们想避免使用JS,因为这不是干净的解决方案。
  3. 我们可以从取消型号上重新加载selectedTerm,然后将其替换为terms列表。但是,为什么我们不得不再次从DB获取一些东西?
  4. 我们可以重新加载整个terms列表。这比第三种解决方案更糟糕。

我们也尝试了内置的重置选项(resetInput标记和其他),但没有用。有没有优雅的方法来解决这个问题,或者我们的建议是正确的?

+0

也许你可以使用RequestScoped bean来保存每个对话框打开时应该重置的属性?并使用PostConstruct拦截器以正确的方式重置它们。 – perissf

+0

使用RequestScoped bean时,在检查复选框时会清除'dateRealization'。另外,它对我们来说可能会有意想不到的行为(我们可能在两个以上的对话框中有这个问题)。但你的答案可以修改为我们的第一个解决方案:保存所有属性而不是应该重置(在克隆对象中),并在单击取消(而不是PostConstruct)后重置它们。 –

+1

可以使用2个具有2个不同作用域的bean,并通过ManagedProperty注释将作用域注入作用域。 – perissf

我会用下面的方法做。

创建的期限一copy constructor

public class Term { 
    private String dummy; 

    public Term() { 

    } 
    //copy constructor 
    public Term(Term another) { 
    this.dummy = another.dummy; // and set the rest of the values 
    } 
} 

和内部DataTable中的按钮调用选择方法。

<p:commandLink value="#{term.subject}" 
      action="#{termRightPanelController.selectTerm(term)}" 
      oncomplete="termRealizeDlg.show();" 
      update=":termRealizeForm:termRealizeDialog" /> 

selectTerm(期限项)

public void selectTerm(Term term) { 
    selectedTerm = new Term(term); 
} 

对话框onHide

<p:dialog id="termRealizeDialog" widgetVar="termRealizeDlg" 
    modal="true" resizable="false" closeOnEscape="true" 
    header="#{termRightPanelController.selectedTerm.subject}" 
    onHide="restDialog()"> 

restDialog() remoteCommand

<p:remoteCommand name="restDialog" 
actionListener="#{termRightPanelController.restDialogValues()}" /> 

restDialogValues()

public void restDialogValues() { 
    setTermRealized(false); 
} 

保存按钮

<p:commandButton value="#{i18n['Common.Save']}" 
    action="#{termRightPanelController.editTerm()}" /> 

editTerm()

public void editTerm() { 
    .... 
    terms.remove(selectedTerm);//assuming equals and hashcode works on ID 
    terms.add(selectedTerm); 
    // Or loop over the terms and find your selectedTerm by id 
    // if the equals and hashcode are not implemented on the ID, 
    //then remove it and add the new one 
    .... 
} 

希望这有助于。

+0

这个解决方案只是克隆,其中克隆方法是由第二个构造函数实现的。这种方法最大的缺点是逐个复制属性。这会乘以我们通过对话框编辑的对象的数量。 –

+0

好吧,它就像克隆,但对我来说,这是避免处理数据库的“唯一”解决方案。 我的意思是你已经列出了4种可能的解决方案,第一种是克隆,克隆是不实际的,因为复制构造函数是。 –